mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2024-12-29 07:29:15 +00:00
0ba83392d4
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included. The Tools directory, containing mostly junk, is also excluded.
9813 lines
376 KiB
Plaintext
9813 lines
376 KiB
Plaintext
;
|
||
; File: PatchIIciROM.a
|
||
;
|
||
; Contains: patches for the ROMs first shipped in a Macintosh IIci ($067C)
|
||
;
|
||
; Copyright: © 1985-1991 by Apple Computer, Inc., all rights reserved.
|
||
;
|
||
; Change History (most recent first):
|
||
;
|
||
; <146> 12/2/91 SAM Using official boxflag equates now.
|
||
; <145> 12/2/91 pvh Added cache flushing to fixup patch table code.
|
||
; <144> 10/28/91 SAM/KSM Rolled in Regatta Changes.
|
||
;
|
||
; Regatta Change History:
|
||
;
|
||
; <15> 8/30/91 SAM Added a check for Tim boxFlag to the code that changes boxFlag
|
||
; from boxTim to BoxTimLC. This prevents non-Tim/TimLC machines
|
||
; using the TERROR ROM with power mgrs and no-FPU being identified
|
||
; as a TimLC.
|
||
; <14> 8/30/91 SAM Added a check for an FPU in the previous backpatch patch so it
|
||
; will not install on machines without one.
|
||
; <13> 8/29/91 SAM Added a check for Zydeco to the "should we remove (ie override)
|
||
; the PACK 4 & 5 SANE rsrcs in ROM" check. (CCH) Added a patch to
|
||
; _FP68k for 030 TERROR machines that will not allow _FP68k calls
|
||
; made from ROM to be backpatched.
|
||
; <12> 8/15/91 SAM (RMP) Added v32SetHandleSize patch. SetHandleSize calls the same
|
||
; common routine that v32SetPtrSize calls, a32SetSize. SetPtrSize
|
||
; was patched earlier to fix a bug in a32SetSize <121> but
|
||
; SetHandleSize was never patched.
|
||
; <11> 8/9/91 SAM Moved the disposal of the Gestalt tables made by ROM to after
|
||
; the reinstallation of Gestalt from disk. This prevents crashes
|
||
; caused by someone calling gestalt after the old tables have been
|
||
; trashed prior to the new table's creation.
|
||
; <10> 8/8/91 SAM (eva) patch level 4 autovector pointed to by vbr, not just the
|
||
; zero-offset cuz when VM is running VBR 0.This routine is a
|
||
; patch to the _VM trap. It fixes a bug in the Terror ROM which
|
||
; occurs when the page the stack is marked uncacheable in the MMU
|
||
; tables, then a subsequent PFLUSH'd is executed with data still
|
||
; in the cache.
|
||
; <9> 8/7/91 SAM Moved the boxFlag slam before Gestalt. Brainfade.
|
||
; <8> 8/6/91 SAM Added a check for TIM LC that will stuff the correct boxFlag
|
||
; into BoxFlag if we're running on a TIm LC. Gestalt's private
|
||
; storage allocated by the ROM version is disposed of prior to
|
||
; reinstalling gestalt from the disk.
|
||
; <7> 8/5/91 SAM (eva) fix patch <6>: Port B dispatcher fixed to call serial
|
||
; service routines and to have same number of bytes before the rts
|
||
; so that async serial driver Rx and SCx patches (which fiddle
|
||
; with return address on stack) return to the proper place.
|
||
; <6> 7/30/91 SAM (eva) fix the Farallon MacRecorder bug by modifing patch to test
|
||
; for port A RxChar and loop back only if we are servicing a channel
|
||
; A interrupt. For port B we just jump to service routine like ROM
|
||
; code.
|
||
; <5> 7/29/91 SAM (eva) patched SCx interrupt handler to fix the StyleWriter bug.
|
||
; On faster machines we are able to send out a byte fast enough
|
||
; after the TBE bit in RR0 gets set that the byte gets written
|
||
; before the TBE interrupt is generated. Instead of just not
|
||
; generating the interrupt, the SCC goes ahead and generates it,
|
||
; but changes the interrupt source code to read 'no interrupt'
|
||
; instead of 'TBE'. This 'no interrupt' code is identical to the
|
||
; 'Special Condition on port B' code, which was the source of our
|
||
; problem. Fix is to just exit SCIntHnd if no special condition
|
||
; bits are set.
|
||
; <4> 7/17/91 SAM (EH) Added Lvl4 irq patch to improve serial performance.
|
||
; <3> 6/30/91 SAM Conditionalizing the SCSI Chaining Bus Error handler for non
|
||
; C96.
|
||
; <2> 6/14/91 SAM Removed the GestaltHardware patch in favor of the real code in
|
||
; GestaltFunction.a. Fixed a check for an unallocated Palette Mgr
|
||
; handle in the InitPalettes Patch. (RMP) Added the IIfx IOP irq
|
||
; MPW fix to the set of Eclipse fixes. (bg) Changed the Egret
|
||
; "CheckPacket()" patch to allow the full
|
||
; range check of possible pseudo-commands.
|
||
; <1> 5/15/91 SAM Split off from 7.0 GM sources. Added code to use PACK 4 & 5 from
|
||
; disk on IIciROM machines that are not TERROR A7 or newer. Do
|
||
; not save GestaltÕs old Logical mem size across PtchInst 5
|
||
; (which is Gestalt) cuz the old number is wrong.
|
||
; 7.0 Change History:
|
||
;
|
||
; <143> 9/18/91 JSM Cleanup header, donÕt include InternalOnlyEqu.a (already in dump
|
||
; file).
|
||
; <142> 8/30/91 DTY Define isUniversal here since itÕs no longer defined in
|
||
; BBSStartup. This file used to use {Defs32}, so isUniversal is
|
||
; defined to be 1.
|
||
; <141> 6/12/91 LN added #include 'ROMPrivateEqu.a'
|
||
; <140> 6/12/91 LN removed #include 'HardwareEqu.a'
|
||
; <139> 4/12/91 dba ewa: add magic signature to Time Manager task used to implement
|
||
; VBLs; the signature will prevent VM from deferring the task
|
||
; <138> 4/8/91 eh Fixed bug in iop serial driver that was causing bad printing to
|
||
; Imagewriter. Actually, it was two bugs. CTS interrupt disable
|
||
; code had a bad branch and the IOP timer never got kickstarted.
|
||
; <137> 4/5/91 eh Fix to Serial driver SerSetbuf call. Missed one place in <135>
|
||
; that sign extended a register.
|
||
; <136> 3/28/91 SAM As per DarinÕs request, I have added a TestFor SCSI96_1Exists
|
||
; before the Quantum 7.9 ROM fix from the Regatta deltas (without
|
||
; forRegattaCPUs).
|
||
; <135> 3/17/91 eh Serial driver status calls 9 and $8000 now return hardcoded
|
||
; driver version instead of getting it from DCE. This obviates the
|
||
; need for the linked patch to _Open to patch the version number
|
||
; in the DCE, a fix which was causing FileShare to crash. Also
|
||
; fixed bug in IOP SerSetBuff (control 9) call -- was sign
|
||
; extending a register unintentionally.
|
||
; <134> 3/8/91 DFH VL,WS#DFH-910308a: Fixed SetEntries patch to not chew on a2.
|
||
; This led to crashes, such as in AfterDark.
|
||
; <133> 3/4/91 dba dty: get rid of SysVers checks
|
||
; <132> 2/26/91 DFH csd,WS#910226a: Fixed bug in ptchPMgrExit where it assumed that
|
||
; graphics has been initialized. Bug introduced by change <124>.
|
||
; <131> 2/25/91 gbm csd, #83338: Fix the fix to Gestalt. Save the original Gestalt
|
||
; globals pointer, and put some important (but hard to figure out)
|
||
; data back in it after the RAM copy installs
|
||
; <130> 2/21/91 gbm csd, #83338: Start including the Gestalt ptch even on ci ROMs.
|
||
; <129> 2/21/91 eh (djw) Fixed bug in serial driver that was preventing use of one
|
||
; port when Nike was printing on the other.
|
||
; <128> 2/19/91 gbm csd, #Go5 approved: Make sure _MemoryDispatch is NOT implemented
|
||
; on machines without PMMUs.
|
||
; <127> 1/29/91 eh (djw) Fixed a bug in the External Status interrupt handler. On
|
||
; port A we crashed on receiving a break if a read was pending
|
||
; because we weren't getting the .Ain DCE ptr properly. Now we get
|
||
; the DCE ptr directly from the Unit table, just like for port B.
|
||
; <126> 1/25/91 eh Fix iop serial driver to: time out an waiting for all-sent in
|
||
; the close, and to disable HWHS properly when external clocking
|
||
; is set.
|
||
; <125> 1/19/91 eh (djw) Patch async serial bypass driver headers to insert
|
||
; signature longword used by linked patch to Open in Serial
|
||
; Patches.a . Added signature longword before already patch IOP
|
||
; driver headers.
|
||
; <124> 1/18/91 dvb Don't restore color environment if it hasn't been changed.
|
||
; Modify SetEntries to mark flag in QDSpare.
|
||
; <123> 1/14/91 eh (djw) Added external clocking support for the NIke printer to
|
||
; the Async Serial Driver.
|
||
; <122> 12/19/90 djw (ewa) Patch ROM SCSIDispatch to the ROM SCSIDispatch to resolve
|
||
; a VM patch conflict.
|
||
; <121> 12/19/90 TL Fixed an old bug in setptrsize for old time sake, in calls
|
||
; between relocRel, the tag is restored in the old block, instead
|
||
; of the new block location. And also discard flag when two block
|
||
; sizes are identical.
|
||
; <120> 12/19/90 dvb Don't draw windowframes after InitGDevice. Removed some
|
||
; duplicate code between PatchIIciROM.a and PaletteMgr.a.
|
||
; <119> 12/15/90 djw (jwk) Add SCSI Mgr support for Quantum 7.9 ROM problem by
|
||
; replacing blind write routine
|
||
; <118> 12/14/90 dnf (jsm) Turn all patches on ExtFSHook off for 7.0 since they have
|
||
; been moved to LaterFileMgrPatches.a
|
||
; <117> 12/14/90 SMC Patched DisposeAppPalettes via PMgrExit to use ApplZone->bklim
|
||
; instead of HeapEnd to determine if palette is in the application
|
||
; heap. Also, patched PMgrExit to only throw away palettes if app
|
||
; is front process. With DFH.
|
||
; <116> 12/14/90 dba <JDR> get rid of VMCalls.a
|
||
; <115> 12/6/90 BBM (dba) Protect the Come-from patches. Eleminate TextFont patch to
|
||
; the MDEF, as the MDEF in ROM is not used anymore, RomOverride at
|
||
; its best.
|
||
; <114> 11/15/90 JSM <bbm> Move come-from patch on _OpenCPort inside NewGWorld to
|
||
; QuickDrawPatches.a.
|
||
; <113> 10/31/90 dba & csd; kill 8¥24 GC loading code for 7.0 (StartSystem.a does it
|
||
; now)
|
||
; <112> 10/22/90 JJ Rex V8: Change VISAChipBit to V8ChipBit.
|
||
; <111> 10/22/90 JJ Rex V8: Change all box flag references to use boxMacLC. Get rid
|
||
; of boxElsie and boxElsieV8.
|
||
; <110> 10/9/90 SAM Updated the AppleTalk _Open patch so that it stuffs PortNotCf
|
||
; into ioResult if SPConfig >= 2.
|
||
; <109> 9/26/90 SAM Redoing the patch to Open that fixes the .MPP crash.
|
||
; <108> 9/25/90 KIP Change Sound Mgr. to a linked patch.
|
||
; <107> 9/18/90 SAM Added changes from SixPack code review (search for <107>).
|
||
; Removed EclipseNOPs (as per BGs request). Fixed the last of the
|
||
; build warnings for this file (rah).
|
||
; <106> 9/15/90 DC added GetGray
|
||
; <105> 9/15/90 GMR Fixed Gestalt parity routine to set good parity before testing
|
||
; the byte with bad parity, so the RPU interrupt would not cause
|
||
; bad data to be stacked.
|
||
; <104> 9/5/90 EH Removed duplicate declarations for PollProc, Pollstack, and
|
||
; HiIntMask from EgretMgr patch <101>.
|
||
; <103> 8/31/90 SAM Adding fix to ReallocHandle patch that checks to see if SysZone
|
||
; = AppZone and if so it only checks the current heap then jumps
|
||
; back to ROM. Added a patch to open so that it clears out the low
|
||
; nibble of SPConfig when the .MPP driver is opened. Made
|
||
; GestaltHardwareAttr recognize Visa/V8.
|
||
; <102> 8/29/90 GMR Fixed Gestalt parity check on FX so it does not destroy A4 (this
|
||
; reg needs to be preserved throughout patches and inits!)
|
||
; <101> 8/22/90 SAM Adding a series of REgret patches & a SANE ptch (search for
|
||
; <101> for more explicit descriptions).
|
||
; <100> 8/20/90 dvb Remove "DrawGrayishText"
|
||
; <99> 8/19/90 SAM Adding changes to make sound (MACE) work on ci ROMs
|
||
; <98> 8/18/90 dba get rid of ptchInst 7 and 8 (Sony Format and Eject patches) as
|
||
; they are now linked patches
|
||
; <97> 8/17/90 gbm start loading soundmgr patch 23 on erickson and elsie, cause
|
||
; BigBang don't work otherwise
|
||
; <96> 8/14/90 DTY Removed TextEditPatchIIciROM since itÕs a linked patch now. (For
|
||
; real this time.) Also deleted an INIT 18 patch for Darin.
|
||
; <95> 8/13/90 JWK NEEDED FOR SIXPACK: Added NuBus and Serial Gestalt selectors.
|
||
; <94> 8/11/90 PKE NEEDED FOR SIXPACK: Fixed bug in previous revision - (per KIP)
|
||
; ptch 3 must load before ptch 23 so SoundMgr globals are
|
||
; initialized!! Was causing ci & fx to hang during boot.
|
||
; <93> 8/10/90 SAM Made ptch 3 (7.0 Sound Mgr) load on all IIciROM machines. It
|
||
; used to *not* load on Erickson/Elsie.
|
||
; <92> 8/8/90 SAM Changing DispatchHelper & ProcHelper into an old style ptch.
|
||
; ¥¥¥--> Temporary <--¥¥¥ Remove when the Sound ptch get converted
|
||
; into an Lptch.
|
||
; <91> 8/7/90 PKE Fixed the SixPack build by adding an eclipseDebug conditional
|
||
; around a BRA.S. Build was broken because BG changed BBSStartup
|
||
; to turn on eclipseDebug for Mac32 (which applies to this file),
|
||
; so EclipseNOPs are expanded and a branch went out of range.
|
||
; Also, altered the previous comment to say needed for SixPack.
|
||
; <90> 8/5/90 PKE NEEDED FOR SIXPACK: Moved installation of Script Mgr ptch 39 and
|
||
; 27 to Mac and A/UX section of install code (was formerly for Mac
|
||
; OS only). Search for <90> to see changes.
|
||
; <89> 7/30/90 SAM Added Egret TickHandler patch so it doesnt loose time while IRQs
|
||
; are off.
|
||
; <88> 7/30/90 dnf Remove installation of ptch 18 (File Manager) and ptch 6 (Btree
|
||
; Manager), now linked patches
|
||
; <87> 7/23/90 dba get rid of ptch 25 for 7.0; it is covered by DialogMgrPatches;
|
||
; get rid of extraneous pre-6.0.6 SysVers conditionals; removed
|
||
; ptchInst 16 since PrGlue is a linked patch
|
||
; <86> 7/21/90 BG Added EclipseNOPs for flakey 040s.
|
||
; <85> 7/20/90 CSL Needed for SIXPACK: Totally replaced Memory manager routine
|
||
; a32SetSize, patch <68> only replaced part of a32SetSize and is
|
||
; not sufficient.
|
||
; <84> 7/20/90 DTY Removed Bass patches since itÕs a linked patch now.
|
||
; <83> 7/20/90 gbm Get rid of some warnings
|
||
; <82> 7/19/90 CCH NEEDED FOR SIXPACK: Removed HwPriv patch since it is now a
|
||
; linked patch.
|
||
; <81> 7/19/90 EH Add VM support for async.a, SetSerBuf control call
|
||
; <80> 7/19/90 GMR Install ptch 7 to change eject track from 79 to 40.
|
||
; <79> 7/18/90 DDG NEEDED FOR SIXPACK: Fixed previous comment.
|
||
; <78> 7/18/90 DDG NEEDED FOR SIXPACK: clean up lomem $B50 after the netbooting socket
|
||
; listener.
|
||
; <77> 7/17/90 DVB Fix DrawGrayishText, and include PaletteMgr.a
|
||
; <76> 7/14/90 DVB Add in new PMgr dispatches
|
||
; <75> 7/11/90 gbm get rid of a few duplicate symbols
|
||
; <74> 7/11/90 DDG NEEDED FOR SIXPACK: Fixed a bug in our new ReadDateTime call. We
|
||
; now return an error code of zero, instead of garbage.
|
||
; <73> 7/2/90 DTY Remove ptchInst 21 since Resource Manager extensions are now in
|
||
; a linked patch.
|
||
; <72> 6/28/90 DDG NEEDED FOR SIXPACK: Put in a fix for egret. Now the
|
||
; _ReadDateTime call does not actually call the clock chip. It
|
||
; simply reads the low mem global (Time) and returns that. This is
|
||
; OK, since Time is automatically updated. This fix only happens
|
||
; on Elsie and Erickson.
|
||
; <71> 6/25/90 DTY Removed ptchInst 9.
|
||
; <70> 6/25/90 KON Remove rSwapMMUMode macro 'cause it's in QDHooks.
|
||
; <69> 6/19/90 VL Remove ptchinst 29 since MiscPatches is a linked patch now.
|
||
; <68> 6/14/90 CSL Needed for Six-Pack. Fixed _setptrsize problem in memory
|
||
; mananger for 32 bit mode only. It will not de-reference from
|
||
; address $0 now.
|
||
; <67> 6/12/90 JSM Remove PtchInst 33 since PPC Toolbox is a linked patch now.
|
||
; <66> 6/7/90 EMT Remove PtchInst 17 since Layer Manager is a linked patch now.
|
||
; <65> 6/7/90 VL Remove PtchInst 28 since HelpMgr is a linked patch now.
|
||
; <64> 5/31/90 DDG Adding a special system error for machines that donÕt have an
|
||
; FPU.
|
||
; <63> 5/31/90 DDG Added the extFS patch from the PatchIIROM.a file. This will fix
|
||
; a strange bug where the wrong error code is being returned from
|
||
; the MountVol call.
|
||
; <62> 5/29/90 DDG NEEDED FOR SIXPACK: Changed all the sixpack conditionals from
|
||
; six-point-oh-seven to six-point-oh-six.
|
||
; <61> 5/17/90 KON Clear high word of d3 and d4 so compare is done as a word in
|
||
; ResizePalette.
|
||
; <60> 5/10/90 JSM AliasMgr now a linked patch, don't install it here anymore.
|
||
; <59> 5/2/90 CCH Fixed bug in parity routine for pre-IIci machines with IIci
|
||
; ROMs.
|
||
; <58> 5/1/90 CCH Added Scrolling throttle and Square menus to misc selector.
|
||
; <57> 4/22/90 csd commented out the installation of SCSI DMA so we stop trashing
|
||
; hard disks on the IIfx.
|
||
; <56> 4/19/90 NB Add PrGlue to the PtchInst list (#16). It's already on all other
|
||
; machines
|
||
; <55> 4/18/90 DDG Rolling in the ReallocHandle patches from the sys6 sources.
|
||
; <54> 4/16/90 DDG Rolled over changes from the split off sources including: a
|
||
; patch to hwPriv, an IOP serial driver fix, SCSI DMA is now
|
||
; disabled on the IIfx due to bugs, added an init (18) to fix the
|
||
; comm toolbox, added the patch for tiburon video cards, added
|
||
; patch 25 (generic system fixes), and finally changed the equate
|
||
; for spline fonts to use the build variable hasSplineFonts.
|
||
; <53> 4/11/90 dba move PPC after B-Tree Manager; get rid of old AppleShare patch
|
||
; for 7.0
|
||
; <52> 3/30/90 DVB Add "WhatPal" PmgrDispatch
|
||
; <51> 3/27/90 PKE Deleted import (currently conditionalized out) of NewSwapIcon,
|
||
; which no longer exists in this PTCH.
|
||
; <50> 3/26/90 PKE Moved definition of symbols that control Script Mgr patch and
|
||
; 'ptch' installation into ScriptPriv.a. Renamed symbols and added
|
||
; some.
|
||
; <49> 3/23/90 NC Added ptch 43 for System 6.0.6 on up. This is for Sound.
|
||
; <48> 3/20/90 DDG Added code to not install patch 3 on Ericksons and above for
|
||
; Sys607 and above.
|
||
; <47> 3/12/90 DVB Fix PMgrExit so that ExitToShell doesn't crash!
|
||
; <46> 3/8/90 JAL Took out include of QuickEqu.a because it is already in
|
||
; StandardEqu.d.
|
||
; <45> 3/4/90 PKE Changed _UprText to _UpperText to match new Traps.a.
|
||
; <44> 3/1/90 GMR Fixed bug in Gestalt parity check for Zone-5, where longword was
|
||
; not being written back with good parity after each SIMM check.
|
||
; <43> 2/28/90 GMR Added include of EgretEqu.a to fix system disk build.
|
||
; <42> 2/28/90 PKE For 7.0, moved Script Mgr ROM patches into ÔptchÕ 39: patches to
|
||
; _Pack6 and _GetIndADB, fixes to String2Date/InitDateCache,
|
||
; installation of some new vectors, and the change to SwapIcon.
|
||
; For all of these except the SwapIcon change, the code is still
|
||
; here but conditionalized differently (in case we need it for
|
||
; 6.1).
|
||
; <41> 2/26/90 EH Rewrote <8.7> to use patch macros. Added on patch for 68000 IOP
|
||
; Serial Driver read bug.
|
||
; <40> 2/23/90 DVB PMgrExit no longer clears the windowlist.
|
||
; <39> 2/22/90 PKE Replaced obsolete _LwrStringToUpr opword with _UprText. Removed
|
||
; setting of temporary sVectFixSpExtra vector (see <12>); we no
|
||
; longer need it.
|
||
; <38> 2/21/90 JS NEEDED FOR 6.0.5: SetDepth also takes a mode
|
||
; <37> 2/16/90 EH Fixed CTS status bug and low baud rate bug in IOP Serial Driver.
|
||
; Fixed <27> to use the patch macros properly.
|
||
; <36> 2/15/90 EMT Moved <1.9> before <1.2> - both patch SetWinColor, SetCtlColor.
|
||
; <35> 2/15/90 DVB Change SetDepth's return to OSErr
|
||
; <34> 2/14/90 DVB Fix SetDepth's register trashage
|
||
; <33> 2/14/90 EH NEEDED FOR 6.0.5: 'Come from' patched IOPMoveData trap to fix
|
||
; IOP Serial Driver DMA hang bug.
|
||
; <32> 2/14/90 CCH NEEDED FOR 6.0.5 - Made sure external cache on Zone 5 does not
|
||
; interfere with the check to see if parity RAM is installed.
|
||
; <31> 2/13/90 SMB NEEDED for 6.0.5 - Added installation code for ptchGetLRPosition
|
||
; and ptchPixelWidths for TextEdit.
|
||
; <30> 2/9/90 EH NEEDED FOR 6.0.5: Patched Level4SccIopInt to set flags such that
|
||
; all the IOP completion routines be called immediately from the
|
||
; IOP Manager, rather than be run as deferred tasks. This, so we
|
||
; don't break Timbuktu/Remote.
|
||
; <29> 2/2/90 JWK NEEDED FOR 6.0.5: Changed SCSI Mgr bus error handler to allow
|
||
; chaining to previously installed handler if a non-SCSI bus error
|
||
; occurs.
|
||
; <28> 2/2/90 GGD NEEDED FOR 6.0.5: Modified the Deferred Task Manager to enable
|
||
; interrupts when returning just so QuickMail servers will
|
||
; continue to work (their bug, but we'll fix them for now).
|
||
; <27> 1/31/90 EH NEEDED FOR 6.0.5: 'Come from' patched IOPMsgRequest trap to fix
|
||
; IOP serial driver control call bug
|
||
; <26> 1/30/90 CCH NEEDED FOR 6.0.5: Modified gestaltHardwareAttr patch to set
|
||
; gestaltHasSCC bit in result if in IOP bypass mode.
|
||
; <25> 1/29/90 GGD NEEDED FOR 6.0.5, Adding a temporary patch to make cmd-period
|
||
; not hang the MPW shell on Zone-5, until the shell can be reved
|
||
; to fix the real problem.
|
||
; <24> 1/29/90 DVB NEEDED FOR 605 - Add PMgrVersion call
|
||
; <23> 1/25/90 KON NEEDED FOR 6.0.5: QDversion is offscreenVersion + $100, not
|
||
; $200.
|
||
; <22> 1/23/90 KON NEEDED FOR 6.0.5: Gestalt now gets the Quickdraw version from
|
||
; GWorld Offscreen version and adds 200.
|
||
; <21> 1/23/90 DVB NEEDED FOR 6.0.5 - Add HasDepth and SetDepth PMgr Dispatches
|
||
; <20> 1/22/90 CCH NEEDED FOR 6.0.5 - Added notification mgr selector.
|
||
; <19> 1/19/90 JWK NEEDED FOR 6.0.5 - Turn on SCSI DMA code in Zone5 final ROM's.
|
||
; <18> 1/18/90 DVB Include PalettePriv.a
|
||
; <17> 1/17/90 CCH NEEDED FOR 6.0.5: moved restoration of cache register in parity
|
||
; check routine.
|
||
; <16> 1/16/90 SMB NEEDED FOR 6.0.5: added install code for TENew and
|
||
; TEStylNew patch and included TextEditPriv.a.
|
||
; <15> 1/16/90 CCH NEEDED FOR 6.0.5: Turn off cache when checking RPU for parity.
|
||
; <14> 1/16/90 KON NEEDED FOR 6.0.5: Added ptch 26
|
||
; <13> 1/12/90 CCH Added include of ÒHardwarePrivateEqu.aÓ.
|
||
; <12> 1/11/90 PKE Initialize Script Manager's new sVectFixSpExtra vector.
|
||
; <11> 1/11/90 DVB Remove _Zaplinks macro.
|
||
; <10> 1/8/90 CCH Added gestaltMiscAttr selector.
|
||
; <9> 1/5/90 GMR Added ptchInst 8; Sony Format patch is now in it's own patch
|
||
; file (FormatPatch.a).
|
||
; <8> 1/5/90 CCH NEEDED FOR 6.0.5. Added parity support for Zone 5, removed base
|
||
; address selectors.
|
||
; <7> 1/4/90 BBM NEEDED FOR 6.0.5. Make the new sound manager patch out the rom
|
||
; on all machines.
|
||
; <6> 1/4/90 PKE NEEDED FOR 6.0.5 (smb's changes from SS-6.0.4b23 to SS-6.0.4f1):
|
||
; ¥ Add install code for TEFindLine patch. ALSO: Updated
|
||
; conditionals so SS-6.0.4 changes go in 6.0.5 as well as 7.0.
|
||
; Cleaned up the BBS header and eliminated the EASE header.
|
||
; <5> 1/3/90 BAL NEEDED FOR 6.0.5: Fixed Zero width character problem in
|
||
; drawtext.
|
||
; <4> 12/19/89 EH REALLY fix the pound signs!
|
||
; <3> 12/19/89 EH try to fix the pound signs!
|
||
; <2> 12/19/89 EH NEEDED FOR 6.0.5: Fix bug in 7.1 async patch; switched registers
|
||
; <1> 12/17/89 CCH Adding for the first time into BBS.
|
||
; <8.8> 12/14/89 SWC NEEDED FOR 6.0.5: Added RecoverHandle patch to also check if the
|
||
; pointer points to a ROM resource. Removed the NewSCSI trap
|
||
; initialization since async SCSI will not be in Zone 5 until 7.0
|
||
; or later.
|
||
; <8.7> 12/14/89 EVA NEEDED FOR 6.0.5 Fix SerialDriver.a patch to check SCCIOPFlag
|
||
; instead of PRAM to see which driver to load
|
||
; <8.6> 12/11/89 smb NEEDED FOR Scripts 604 AND (6.0.5 <= SysVers < 7.0): added
|
||
; installation code for TE routines CaretInsideRun,
|
||
; InvrtRectangle, SetKeyboard2Font.
|
||
; <8.5> 12/8/89 PKE NEEDED FOR Scripts604 AND FOR (6.0.5 <= SysVers < 7.0): Patch
|
||
; LwrString to handle 2-byte chars via Transliterate (yuck). For
|
||
; 7.0, we do this elsewhere.
|
||
; <8.4> 11/29/89 GGD NEEDED FOR 6.0.5: Re-Enabled the SANE optimization to bypass the
|
||
; Package Manager which never made it into 6.0.4. Fixed bug
|
||
; StripAddress that caused it to sometimes not strip when in a
|
||
; interrupt handler. Modified ADB auto/srq polling to not poll
|
||
; device addresses that are not in the device table. On OSS based
|
||
; machines, install a time manager task to simulate a 60.15Hz
|
||
; pseudo VBL because the OSS generates a 60.00Hz interrupt which
|
||
; is the wrong frequency.
|
||
; <8.3> 11/28/89 dvb Fixed bug in PMgr Zaplinks by working over pmgrDispatch. Also
|
||
; fixed bug in dispatch.
|
||
; <8.2> 11/22/89 EMT NEEDED FOR 6.0.5: Added humane scrolling.
|
||
; <8.1> 11/21/89 smb Added installation code for TE routines ptchGetWidth and
|
||
; ptchGetRLPosition.
|
||
; <8.0> 11/17/89 PKE Tail patch on _GetIndADB to fix Script Mgr SwapKybd routine,
|
||
; which cleared ADB keyboard driver dead state as a word: should
|
||
; be a long.
|
||
; <7.9> 11/10/89 KON PTCH'ed GetNewCWindow so when a palette with the same ID as the
|
||
; window exists in the resource file, the palette is attached to
|
||
; the window.
|
||
; <7.8> 11/6/89 PKE NEEDED FOR 6.0.5!! Bug fixes for InitDateCache and String2Date
|
||
; needed for HyperCard. InitDateCache: Fixed CopyArray to use
|
||
; correct register (A4) for source pointer, and to initialize all
|
||
; relevant bytes of length register (D0). String2Date: if first
|
||
; relevant (i.e., day or month name) alpha token is a month name,
|
||
; we now search the day name list if we find another alpha token
|
||
; (fixes BRC #54946). Rearranged Cache structure to fix invalid
|
||
; use of month/day name index.
|
||
; <7.7> 10/12/89 smb Moved TextEdit patches to TextEditPatchIIciROM.a. Fixed bug in
|
||
; old highlighting code that I introduced accidently (changed
|
||
; move.w -> move.l).
|
||
; <7.6> 10/11/89 CCH Added INCLUDE of "MMUEqu.a"
|
||
; <7.5> 10/11/89 CCH Set up MMUType if not already initialized.
|
||
; <7.4> 10/6/89 JSM Removed SnarfMan 'ptch', now PACK 13.
|
||
; <7.3> 10/5/89 CCH Changed an ORI to a BSET in gestaltAddressingModeAttr patch, and
|
||
; added installation of it.
|
||
; <7.2> 10/5/89 smb Added old highlighting code for TextEdit for HyperCard
|
||
; outlining.
|
||
; <7.1> 10/5/89 EVA NEEDED FOR 6.0.5!!! Fixed bug in async serial driver Ext/Stat
|
||
; int handler
|
||
; <7.0> 10/4/89 smb Fixed 6.0.4 build by moving around some of my conditionals due
|
||
; to dependencies! Fixed TEInit to set TEDoText like it used to.
|
||
; Cleaned up TEOutlineHilite. Fixed caret display for outline
|
||
; highlighting.
|
||
; <6.9> 9/29/89 CCH Added patch for gestaltAddressingModeAttr selector to add
|
||
; gestalt32BitCapable attribute. (version 6.8 breaks 6.0.4 builds,
|
||
; so I just tested on bigbang - because alpha 0 is in two days,
|
||
; thats why)
|
||
; <6.8> 9/29/89 smb Added patches for TextEdit for TEFeatureFlag, SetFont2Keyboard,
|
||
; and fixed CursorMovement for double-byte characters.
|
||
; <6.7> 9/27/89 EMT Fixed 6.2 to use Lea rather than LeaROM for RAM address.
|
||
; <6.6> 9/26/89 CVC Added PPC Toolbox as a 'ptch'.
|
||
; <6.5> 9/25/89 EMT Added ptchs 18, 6, 29.
|
||
; <6.4> 9/19/89 RLC Add Balloon Help (ptch 28) to this file.
|
||
; <6.3> 9/18/89 BBM Install resource manager extensions, ptch 21
|
||
; <6.2> 9/18/89 PKE For 7.0, patch Script Manager internal routine SwapIcon to use
|
||
; new 'kscn' resource type instead of 'SICN'.
|
||
; <6.1> 9/17/89 PKE Decided to patch out GetScript/SetScript entirely in ptch 27, so
|
||
; we no longer patch them here (see 5.9). Also, for 7.0 we now
|
||
; install the Script Manager's Gestalt function in ptch 27 instead
|
||
; of here (see 2.5).
|
||
; <6.0> 9/12/89 EMT PaintOne patch (3.7) nukes the layer manager. Only use on pre
|
||
; 7.0 systems.
|
||
; <5.9> 9/6/89 PKE Patch Script Manager GetScript/SetScript routines to support
|
||
; additional font info verbs for 7.0, and set up this font info in
|
||
; Roman ScriptRecord. Set new sVectCallInterface vector. Redo
|
||
; Script Manager version setup, using new smgrVersPTCHRom equate.
|
||
; <5.8> 9/5/89 jwk NEEDED FOR 6.0.5: Turn on NewSCSI in ROM if on F19.
|
||
; <5.7> 9/4/89 PKE Install Script Manager 7.0 extensions, ptch 27. Set Script Mgr
|
||
; version for 7.0.
|
||
; <5.6> 8/31/89 JSM Added SnarfMan support.
|
||
; <5.5> 8/30/89 smb NEEDED FOR Scripts604 and Big Bang! Bug fix in ptchTEFindWord
|
||
; (fixed word dragging bug and now uses old FindWord code when
|
||
; RecalLines calls. Also added ptchMeasureWidth to fix a
|
||
; hilighting bug at line ends when the line direction is RL on a
|
||
; system that is normally LR (ie - Roman, Kanji, etc.)
|
||
; <5.4> 8/28/89 PKE For 7.0, initialize additional Script Mgr vectors for
|
||
; SMgrCalcRect and SMgrInitFonts.
|
||
; <5.3> 8/27/89 PKE NEEDED FOR Scripts604, 6.0.5: Bump Script Manager version for
|
||
; Scripts604 or SysVers > $604, since IntlForce bug fix (4.5) is
|
||
; installed.
|
||
; <5.2> 8/22/89 PKE NEEDED FOR 6.0.4: (really dba) Tail patch to TextFont which
|
||
; fixes an MDEF bug in calculating the icon height. Replaces
|
||
; GetResource patch in 3.7 which attempted to fix the same
|
||
; problem.
|
||
; <5.1> 8/21/89 PKE NEEDED FOR 6.0.4: Really put in 4.1, which was only present as a
|
||
; comment until now (although it existed on Fiction sources).
|
||
; <5.0> 8/21/89 PKE NEEDED FOR 6.0.4: (really CSD) Fixed MDEF 3.7 patch (again. Last
|
||
; time, right?) to load #$00200020 into D1 when appropriate
|
||
; instead of jumping back into ROM at the same place for both
|
||
; cases cicn found and cicn not found.
|
||
; <4.9> 8/21/89 PKE NEEDED FOR 6.0.4: (really dba) Changed MDEF patch 3.7 to load A0
|
||
; with the right value instead of preserving its value.
|
||
; <4.8> 8/21/89 PKE NEEDED FOR 6.0.4: (Per CSD) Correct ROMNoColor address in MDEF
|
||
; patch (part of 3.7).
|
||
; <4.7> 8/21/89 PKE NEEDED FOR 6.0.4:
|
||
; ¥ (per dba) Only re-load the standard clut into QDColors if
|
||
; QDColors exists; this is so that A/UX will work
|
||
; ¥ Conditionalize 4.5 for Scripts604 OR (SysVers > $604)
|
||
; <4.6> 8/21/89 PKE NEEDED FOR 6.0.4!: Patch RelString,UprString,CmpString to
|
||
; re-introduce the bug in which "`" is converted to uppercase as
|
||
; "a". This is necessary to prevent HFS problems, since existing
|
||
; disk catalogs use the old, buggy sorting. Also remove SANE
|
||
; optimization (2.0); breaks Excel.
|
||
; <4.5> 8/21/89 PKE NEEDED FOR 6.0.4 SCRIPTS BUILD, 6.0.5: Extend Pack6 patch to fix
|
||
; a problem in LwrString,CharType,Transliterate,FindWord. These
|
||
; routines should save the IntlForce flags then clear them before
|
||
; the IUGetIntl call, restoring the flags afterward. This is so we
|
||
; get the itl2 tables for the correct script (instead of the
|
||
; tables for the system script).
|
||
; <4.4> 8/21/89 PKE NEEDED FOR 6.0.4!: Fixed accidental deletion of INCLUDE
|
||
; 'VideoPatch.a' in (4.3).
|
||
; <4.3> 8/21/89 PKE NEEDED FOR 6.0.4!!: Patch Pack6 to fix me-too problem with
|
||
; pointer to unlocked handle in Transliterate; affects Roman
|
||
; system (this problem looks familiar; did I dream that I already
|
||
; fixed this one?).
|
||
; <4.2> 8/18/89 smb NEEDED FOR 6.0.4: Another unlocked handle problem!
|
||
; AAAARRRRRGGGGHHHHHH! (See ptchOnSameLine below)
|
||
; <4.1> 8/18/89 DAF FOR 6.0.4 BUILD - Fixed a bug on non-CLUT devices in the
|
||
; SaveEntries trap on Aurora
|
||
; <4.0> 8/16/89 dba NEEDED FOR 6.0.4: InitProcMenu bug fixed: MBDF ID was not put in
|
||
; MenuList if MenuList was already allocated (InitMenus already
|
||
; called)
|
||
; <3.9> 8/15/89 prp Added Alias Manager and Folder Manager support.
|
||
; <3.8> 8/15/89 smb NEEDED FOR 6.0.4: Fixed some problems in my patch code for the
|
||
; bad pointer bug.
|
||
; <3.7> 8/15/89 dba NEEDED FOR 6.0.4:
|
||
; ¥ Shortened the SetWin/CtlColor patch by returning to ROM earlier.
|
||
; ¥ Patch PaintOne to do nothing if WWExist is non-0.
|
||
; ¥ Patch OpenCPort so that the current port is saved across
|
||
; NewGWorld.
|
||
; ¥ Patch GetResource so that GetIconSize in MDEF does not trash A0.
|
||
; ¥ Moved VideoPatch.a so that it does not happen on A/UX.
|
||
; ¥ Re-load the standard clut into QDColors so that the green channel
|
||
; is fixed
|
||
; <3.6> 8/14/89 djw NEEDED FOR 6.0.4: Fixed bug in slot mgr in pInitEntry routine.
|
||
; When calling _InsertSRTRec, and the sRsrc has a refnum
|
||
; associated with it, _sFindDevBase has bad spId.
|
||
; <3.5> 8/13/89 BAL NEEDED FOR 6.0.4: Added tail patch to InitPalettes to defeat
|
||
; spurious ExitToShell patching code (leftover from JP builds).
|
||
; (dvb really)
|
||
; <3.4> 8/11/89 smb Finally rolled in patches for a bad pointer bug (#51602) and an
|
||
; up & down arrow keys bug (#51961). See comments below.
|
||
; <3.3> 8/11/89 djw NEEDED FOR 6.0.4: Cleaned up file by deleting old comments,
|
||
; adding new comments, laying out patches in a "prettier" and more
|
||
; orderly format. Added A/UX runtime conditional check for
|
||
; Mac-only patches. Moved patches <2.4> and <2.7> to Mac OS only.
|
||
; Modified slot manager calls in patche <2.1> as per code review.
|
||
; <3.2> 8/9/89 CCH NEEDED FOR 6.0.4: Added patch to gestaltQuickdrawVersion to
|
||
; return two digit versions.
|
||
; <3.1> 8/8/89 smb NEEDED FOR 6.0.4: Reverted TEFindWord patch since the previous
|
||
; patch introduces an uglier bug that won't be fixed now. Also
|
||
; added gestalt function for TE.
|
||
; <¥3.0> 8/8/89 dba RealityÕs hard disk was full! Try submitting again.
|
||
; <3.0> 8/8/89 dba NEEDED FOR 6.0.4: added Menu Manager patches; InitProcMenu patch
|
||
; because it simply didnÕt work; MenuSelect patch to reinstate
|
||
; WaitMouseUp check
|
||
; <2.9> 8/8/89 PKE NEEDED FOR 6.0.4: In gestaltScriptMgr function, if gestalt
|
||
; selector is undefined, just leave gestalt result alone.
|
||
; <2.8> 8/8/89 smb NEEDED FOR 604: Added more TE patches for Aurora!
|
||
; <2.7> 8/7/89 GGD Changed SIntInstall again, to leave $FF as highest priority, but
|
||
; reverse handling of equal priorities. Modified to use less
|
||
; space. Changed GetBoardROM from <2.4> to be a ROM Offset,
|
||
; instead of absolute ROM address.
|
||
; <2.6> 8/6/89 DAF FOR 6.0.4 BUILD - Added TFB video card driver override for boot
|
||
; screen. This is the same code as is included in PatchIIROM.a
|
||
; (VideoPatch.a)
|
||
; <2.5> 8/5/89 PKE NEEDED FOR 6.0.4: Add Gestalt function for Script Manager,
|
||
; install corresponding Gestalt selectors.
|
||
; <2.4> 8/4/89 djw NEEDED FOR 6.0.4: Deleted patch <1.3> (no longer needed). Added
|
||
; code to re-init board id's in slot pram (fixes a bug in Aurora
|
||
; in InitPRAMRecs).
|
||
; <2.3> 8/2/89 EVA (forgot to) include hardwareEqu.a and SlotMgrEqu.a
|
||
; <2.2> 8/2/89 EVA FOR 6.0.4 (and above) Patched _SIntInstall to reverse slot
|
||
; interrupt queueing order
|
||
; <2.1> 8/1/89 CSD FOR 6.0.4: Added patch to suppress appleshare arrows on 32-bit
|
||
; video cards.
|
||
; <2.0> 7/26/89 GGD NEEDED FOR 6.0.4 Added SANE optimization to bypass the package
|
||
; manager
|
||
; <1.9> 7/25/89 DAF FOR 6.0.4 BUILD - Fixes for SetWinColor, SetCtlColor in 32-bit
|
||
; mode
|
||
; <1.8> 7/25/89 smb NEEDED FOR 6.0.4: Added TextEdit patches for Aurora.
|
||
; <1.7> 7/3/89 NJC Sound Manager Extensions (ptch 23) rolled in for real.
|
||
; <1.6> 6/21/89 NJC Added a ptchinst 3 to if it wasn't already there and added in a
|
||
; commented-out ptchinst 23 for the sound dispatcher,DJ, and S.M.
|
||
; enhancements.
|
||
; <1.5> 5/31/89 CEL Only defined Spline_Font variable if it is undefined - makes it
|
||
; easier to build test 6.0.4 systems
|
||
; <1.4> 5/22/89 AG Fixed my mistake in gettrapaddress call
|
||
; <1.3> 5/21/89 AG Remove NEW SCSI manager trap (A089)
|
||
; <1.2> 5/13/89 EMT Added Window Manager extensions (Layers).
|
||
; <1.1> 5/3/89 CEL Rolling in Bass for the first time into EASEÉ
|
||
; <1.0> 3/6/89 CCH Adding to EASE for first time.
|
||
;___________________________________________________________________________________________________
|
||
; To Do:
|
||
;
|
||
;___________________________________________________________________________________________________
|
||
|
||
IF (&TYPE('SPLINE_FONT') = 'UNDEFINED') THEN
|
||
SPLINE_FONT EQU hasSplineFonts ;<1.1-4april89-CEL> <DDG>
|
||
ENDIF
|
||
|
||
IF (&TYPE('Scripts604') = 'UNDEFINED') THEN
|
||
Scripts604 EQU 0 ;<4.7><08/21/89 pke>
|
||
ENDIF
|
||
|
||
if (&type('isUniversal') = 'UNDEFINED') then
|
||
isUniversal: equ 1 ; <142> Define isUniversal here instead of BBSStartup
|
||
endif
|
||
|
||
BLANKS ON
|
||
STRING ASIS
|
||
MACHINE MC68020 ; changed from MC68000 to MC68020 <24July89smb>
|
||
MC68881
|
||
|
||
LOAD 'StandardEqu.d' ;
|
||
INCLUDE 'PatchMacros.a'
|
||
INCLUDE 'SlotMgrEqu.a' ;<2.3>
|
||
INCLUDE 'HardwarePrivateEqu.a'
|
||
INCLUDE 'UniversalEqu.a' ;<7.1>
|
||
INCLUDE 'VideoEqu.a'
|
||
INCLUDE 'ROMEqu.a'
|
||
INCLUDE 'MMUEqu.a' ;<7.6>
|
||
Include 'ScriptPriv.a' ;
|
||
INCLUDE 'GestaltEqu.a' ;
|
||
INCLUDE 'GestaltPrivateEqu.a' ;
|
||
INCLUDE 'TextEditPriv.a' ; <1/16/90smb> <16>
|
||
INCLUDE 'PackMacs.a' ;
|
||
INCLUDE 'InternalMacros.a' ; <54>
|
||
|
||
INCLUDE 'PaletteEqu.a' ;
|
||
INCLUDE 'PalettePriv.a'
|
||
INCLUDE 'ApplDeskBus.a' ; <8.0>
|
||
INCLUDE 'EgretEqu.a' ; <43>
|
||
INCLUDE 'IOPEqu.a' ; <8.4>
|
||
INCLUDE 'AppleDeskBusPriv.a' ; <8.4>
|
||
INCLUDE 'SCSIEqu.a' ; <19>
|
||
INCLUDE 'SCSIPriv.a' ; <19>
|
||
|
||
include 'ColorEqu.a'
|
||
INCLUDE 'QDHooks.a'
|
||
|
||
TERRORmajorVers EQU $067C ; TERROR major ROM version
|
||
TERRORminorVers EQU $15 ; TERROR ROM minor version number
|
||
ZYDECOminorVers EQU $17 ; Zydeco ROM minor version number
|
||
|
||
; The following symbols are defined in ScriptPriv.a. They control whether <50>
|
||
; various Script Mgr patches are resident and installed here (since many
|
||
; are also included in 'ptch' 39 or 27), and also control installation of
|
||
; Script Mgr 'ptch' resources.
|
||
;
|
||
; doScriptMgrGestalt ; in ptch 27
|
||
; doScriptMgrPack6Fix ; in ptch 39
|
||
; doScriptMgrStr2DatFix ; in ptch 39
|
||
; doScriptMgrRstKCHRFix ; in ptch 39
|
||
; doScriptMgrLwrString2 ; in ptch 27
|
||
; doScriptMgrSetROMVers ; in ptch 39
|
||
; doScriptMgrNewVectors ; in ptch 39
|
||
; installScriptMgrPtch27
|
||
; installScriptMgrPtch39
|
||
;
|
||
;-------------------------------------------------------------------------------
|
||
|
||
ROM67CFix PROC EXPORT
|
||
IMPORT PatchInit
|
||
EXPORT StartPatch,CutBack
|
||
|
||
; Cut back Code:
|
||
;
|
||
; StartPatch is the entry point for ROM67CFix. Upon entry D1.L contains our handle.
|
||
;
|
||
|
||
StartPatch
|
||
Bra PatchInit ; Carry out the patches <1.1-4april89-CEL>
|
||
DC.B 'PTCH' ; resource type
|
||
DC.W $67C ; patch ID $67C.
|
||
DC.W 1 ; current version number.
|
||
|
||
; cut back the ram-based system code to exclude this initialization code
|
||
; d0 = size to cut patch down to (EndOfPatch - StartPatch)
|
||
; a0 = handle to this PTCH resource (passed into StartPatch in D1 from SysPatch)
|
||
|
||
CutBack
|
||
_SetHandleSize ; adjust our size <1.1-4april89-CEL>
|
||
MOVEQ #$7F,D0 ; a soon to be large number
|
||
SWAP D0
|
||
_CompactMem ,SYS ; of course there must be a comma!
|
||
RTS ; all done
|
||
ENDPROC ; <24July89smb>
|
||
|
||
|
||
|
||
;=========================================================================================
|
||
;=========================================================================================
|
||
;= =
|
||
;= RESIDENT PATCH INSTALL CODE IS BELOW THIS POINT =
|
||
;= =
|
||
;= Add patch code which remains resident in the system in the following section. The =
|
||
;= installation code for the resident patches are further down in the file. Please =
|
||
;= begin your patch code with a header which serves to delimit your code from the =
|
||
;= previous person's patch code. Use another patches header as an example. Leave at =
|
||
;= least 2 or 3 blank lines between your code and the next code. Be sure to be careful =
|
||
;= about your conditionals. The safest thing to do is to make your code self-contained =
|
||
;= and not depend on someone elses conditionals encompassing your code. =
|
||
;= =
|
||
;= To find a place to insert your resident patch code, search for 'EndOfPatch' =
|
||
;= =
|
||
;= Please be neat and follow the format =
|
||
;= Drive safely =
|
||
;= =
|
||
;=========================================================================================
|
||
;=========================================================================================
|
||
|
||
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
||
;********************** PaletteMgr Patches Start Here ************************
|
||
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
||
INCLUDE 'paletteMgr.a'
|
||
|
||
|
||
ptchInitPalettes PROC EXPORT
|
||
RomInitPalettes EQU $3E1F0
|
||
; <dvb 8 August 1989> 3.5
|
||
; This neutralizes some spurious code in InitPalettes that patches ExitToShell
|
||
; the first time [InitPalettes is called and MultiFinder is active]. We depend
|
||
; on getting at least one InitPalettes before MultiFinder (from INIT 31).
|
||
JSRRom RomInitPalettes ; Call the old one.
|
||
MOVE.L PMgrHandle,A0 ; A0 = handle to pm globals
|
||
MOVE.L A0,D0 ; Are we a pmgr?
|
||
BEQ.S ptchIPEnd ; No=>bye.
|
||
CMPI.L #-1,D0 ; Is it -1? <2>
|
||
BEQ.S ptchIPEnd ; -> Yes, bail out. <2>
|
||
MOVE.L (A0),A0 ; A0->pm globals
|
||
TST.L OldExitToShell(A0) ; Has it been patched yet?
|
||
BNE.S ptchIPEnd ; Yes => do nothing
|
||
MOVE #1,OldExitToShell(A0) ; Put something there; pretend its patched
|
||
|
||
ptchIPEnd RTS
|
||
ENDPROC
|
||
|
||
|
||
;-------------- Start of PMgrDispatch patch added by dvb 28Nov89 <8.3> --------------------
|
||
|
||
|
||
PROC
|
||
EXPORT ptchPMgrDispatch,pMgrProcs,pMgrProcsEnd
|
||
IMPORT SetDepth,HasDepth,PMgrVersion
|
||
IMPORT SetPaletteUpdates,GetPaletteUpdates,CheckColors
|
||
IMPORT GetGray
|
||
|
||
RomEntry2Index EQU $3E8C0
|
||
RomIndex2Entries EQU $3E9A0
|
||
RomDeltaRGB EQU $3CBF0
|
||
RomNewHiliteColor EQU $3F8D0
|
||
RomPMgrExit EQU $3DAA0
|
||
RomSaveFore EQU $3F910
|
||
RomSaveBack EQU $3F914
|
||
RomRestoreFore EQU $3F970
|
||
RomRestoreBack EQU $3F98E
|
||
RomReinstantiateColors EQU $3F9B0 ;this routine should do something heh heh
|
||
RomReleaseList EQU $3F9C0
|
||
RomPMgrDispatch EQU $3FA36
|
||
RomPMgrFinalError EQU $3FA4A
|
||
RomRestoreDeviceClut EQU $3F8A0
|
||
RomResizePaletteplusEight EQU $3F818
|
||
RomFindLink EQU $3E460
|
||
RomUnhookAfterZapLinks EQU $3F61E
|
||
RomUnhookGoHome EQU $3F642
|
||
|
||
RomZapLinksAtA EQU $3F70A
|
||
|
||
;ctReserveBit EQU 6
|
||
|
||
ptchResizePalette
|
||
;---------------------------------------------------
|
||
;
|
||
; PROCEDURE ResizePalette(srcPalette:PaletteHandle; dstSize:INTEGER); AAA2/3;
|
||
;
|
||
; Set the number of entries in the palette, and properly dispose of some
|
||
; of them if the palette is shrinking.
|
||
|
||
;ResizePalette PROC EXPORT
|
||
RPVars RECORD {A6Link},DECREMENT
|
||
result DS.B 0 ; Result: none
|
||
srcPal DS.B 4 ; input: palette handle
|
||
dstSize DS.B 2 ; input: new size for palette
|
||
return DS.B 4
|
||
A6Link DS.B 4 ; old contents of A6
|
||
|
||
linkSize DS.B 0 ;linky number
|
||
ENDR
|
||
|
||
WITH RPVars
|
||
LINK A6,#linkSize
|
||
MOVEM.L A2/D3-D4,-(SP) ; save 'em.
|
||
moveq #0,d3 ;<KON 17May90>
|
||
move.l d3,d4 ;<KON 17May90>
|
||
JMPRom RomResizePaletteplusEight
|
||
|
||
ptchZapLinks
|
||
; Following code is spliced out of CQD:PaletteMgr.a <dvb>
|
||
; ROM67C: Zaplinks bug is that it doesn't clear the ctReserve bit if its
|
||
; not on the main screen. Zaplinks is called by Pillage, UnreserveDevices,
|
||
; and ReleaseList. Pillage and UnreserveDevices end up clearing the bit
|
||
; themselves, so only ReleaseList must be patched here.
|
||
;
|
||
|
||
ZLVars RECORD {A6Link},DECREMENT
|
||
result DS.B 0 ;Result length: none
|
||
myIndex DS.B 2 ;Input: device number and index to unlink
|
||
return DS.B 4
|
||
A6Link DS.B 4 ;old contents of A6
|
||
|
||
linkSize DS.B 0 ;linky number
|
||
ENDR
|
||
|
||
WITH ZLVars
|
||
|
||
LINK A6,#linkSize
|
||
MOVEM.L A0-A2/D0-D4,-(SP)
|
||
|
||
MOVE.L PMgrHandle,A1
|
||
MOVE.L (A1),A1 ; A1->PMgrData
|
||
LEA LinkTabs(A1),A0 ; A0->Link Tables
|
||
MOVE.L PListHandle(A1),A2 ; A2 = palette list handle
|
||
MOVE.L (A2),A2 ; A2 -> palette info list
|
||
MOVE myIndex(A6),D0 ; D0 = tricky link
|
||
AND #$1FFF,D0 ; clear key bits
|
||
|
||
MOVE D0,D1
|
||
LSR #8,D1 ; D1 = device number
|
||
MOVE.L DevHandles(A1,D1*8),A1 ; A1 = device handle
|
||
MOVE.L (A1),A1 ; A1->device
|
||
MOVE.L gdPMap(A1),A1 ; A1 = pixmap handle
|
||
MOVE.L (A1),A1 ; A1->pixmap
|
||
MOVE.L pmTable(A1),D1 ; D0 = color table for this device
|
||
BEQ.S @a ; Skip this if none
|
||
MOVE.L D1,A1 ; A1 = color table handle
|
||
MOVE.L (A1),A1 ; A1 -> color table
|
||
CLR D1
|
||
MOVE.B D0,D1 ; We need to clear the upper bits
|
||
CMP ctSize(A1),D1 ; Index in range? <fixed>
|
||
BHI.S @a ; No=>skip this
|
||
BCLR #ctReserveBit,ctTable+value(A1,D1*8) ; unreserve!
|
||
|
||
@a JMPRom RomZapLinksAtA ; return to ROM code
|
||
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; PROCEDURE PMgrExit; AAA2/12;
|
||
;
|
||
; Someone should call here when an application quits. Please.
|
||
;
|
||
ptchPMgrExit
|
||
|
||
PXVars RECORD {A6Link},DECREMENT
|
||
result DS.B 0 ;Result: nothing
|
||
return DS.B 4
|
||
A6Link DS.B 4 ; old contents of A6
|
||
frontPSN DS.B 8 ; a 64-bit process serial number
|
||
myPSN DS.B 8 ; likewise
|
||
inFront DS.B 2 ; a boolean
|
||
linkSize DS.B 0 ; linky number
|
||
ENDR
|
||
|
||
ROMINTOPMGREXIT EQU $3DAB2
|
||
|
||
WITH PXVars
|
||
MOVE.L WindowList,-(SP) ; Save the windowlist value
|
||
LINK A6,#linkSize
|
||
|
||
TST.B QDExist ; if InitGraf has not been called yetÉ
|
||
BNE.S @doNothing ; (a5) not valid and there is nothing to do
|
||
CMP.L #PMgrNil,PMgrHandle ; If the palette manager doesnt exist...
|
||
BEQ.S @doNothing
|
||
CLR.L AppPalette
|
||
BSR.S DisposeAppPalettes
|
||
|
||
MOVE.L (A5),A0 ; < 124 >
|
||
BTST #3,QDSpare0(A0) ; Any change to color env? < 124 >
|
||
BEQ.S @doNothing ; < 124 >
|
||
|
||
BSR.S CheckForProcessMgr
|
||
BEQ.S @front ; if no process mgr, assume we're in front
|
||
MOVE #$0100,inFront(A6) ; default inFront to true
|
||
SUBQ #2,SP ; space for result
|
||
PEA frontPSN(A6)
|
||
_GetFrontProcess
|
||
TST (SP)+ ; problem getting front psn?
|
||
BNE.S @front ; YES => just zap the cluts
|
||
CLR.L myPSN(A6)
|
||
MOVE.L #kCurrentProcess,myPSN+4(A6)
|
||
SUBQ #2,SP ; space for OSErr result
|
||
PEA frontPSN(A6)
|
||
PEA myPSN(A6)
|
||
PEA inFront(A6)
|
||
_SameProcess ; are we the front process?
|
||
ADDQ #2,SP ; OSErr leaves inFront true from above
|
||
TST inFront(A6)
|
||
BEQ.S @doNothing
|
||
@front
|
||
JSRROM ROMINTOPMGREXIT
|
||
; JSR CheckAllDeviceCluts ; A pretty simple patch, really.
|
||
; CLR -(SP) ; No Setentries on Scatter
|
||
; JSR ScatterDevices
|
||
; BSR.S CheckForJuggler ; Is Jugglertm active?
|
||
; BNE.S @doNothing ; No=>WMgr is void, next line dangerous
|
||
; JSR UpdateDevices
|
||
; MOVE.L mainDevice,theGDevice
|
||
@doNothing
|
||
UNLK A6
|
||
MOVE.L (SP)+,WindowList
|
||
RTS
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; FUNCTION CheckForProcessMgr:Boolean;
|
||
;
|
||
; Determine if the process mgr is present using Gestalt.
|
||
; (we assume that gestaltLaunchControl iff processMgr is here)
|
||
; Affect only A0/D0, since Gestalt is an OS trap.
|
||
; return Z-flag Clear if the process mgr is here (BNE ProcMgrTrue)
|
||
|
||
CheckForProcessMgr
|
||
MOVE.L #'os ',D0 ; type of question
|
||
_Gestalt
|
||
TST D0 ; OSErr from Gestalt?
|
||
BEQ.S @a ; No=>test result
|
||
SUBA A0,A0 ; Yes=>assume there's no procMgr
|
||
@a
|
||
MOVE.L A0,D0
|
||
BTST #gestaltLaunchControl,D0 ; clear the Z-flag if procmgr here
|
||
RTS
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; PROCEDURE DisposeAppPalettes();
|
||
;
|
||
; Look through the palette list and dispose of any in the current App heap.
|
||
|
||
DisposeAppPalettes
|
||
|
||
MOVEM.L A0-A3/D0-D3,-(SP) ; save all registers
|
||
MOVE.L PMgrHandle,A2 ; get paletteMgr handle
|
||
CMP.L MinusOne,A2 ; is it there?
|
||
BEQ GoHome ; => no, just return
|
||
MOVE.L (A2),A1 ; point to data structure
|
||
MOVE.L PListHandle(A1),A0 ; get handle to palette list
|
||
_HLock ; and lock it down
|
||
MOVE.L (A0),A3 ; point to palette list
|
||
|
||
Move APalettes(A1),D3 ; get number of active handles
|
||
Beq.s NoPals ; no friends => go home
|
||
Add FreeSpaces(A1),D3 ; calculate total number of entries
|
||
;<13> Clr.L WindowList ; clear the list of windows for FrontWindow AWC.PB506
|
||
BRA.S FindEnd ; => check for no entries
|
||
|
||
FindLoop Move.L PaletteRef(A3),D1 ; get first entry
|
||
BEQ.S FindNext ; => no palette in entry
|
||
MOVE.L ApplZone,A0 ; get application heap zone <117>
|
||
CMP.L A0,D1 ; Are we before the heap zone? <117>
|
||
BLO.S FindNext ; Yes => not in app heap
|
||
CMP.L bklim(A0),D1 ; Are we past the heap zone <117>
|
||
BHS.S FindNext ; => not in app heap
|
||
MOVE.L D1,-(SP) ; push palette handle
|
||
_DisposePalette ; and dispose it in place
|
||
FindNext AddQ #PLstEntrySz,A3 ; bump to the next entry
|
||
FindEnd DBra D3,FindLoop ; repeat for all spaces
|
||
|
||
NoPals MOVE.L (A2),A1 ; point to palette stuff
|
||
MOVE.L PListHandle(A1),A0 ; get handle to palette list
|
||
_HUnlock ; and unlock it
|
||
|
||
GoHome Clr.L AppPalette ; set us up for the next guy AWC.PB508
|
||
|
||
MOVEM.L (SP)+,A0-A3/D0-D3
|
||
RTS
|
||
|
||
; This is the Palette Manager's dispatch table. ROM routines
|
||
; which work are included with DcRom to give absolute
|
||
; addresses. New routines are offsets from the table base, with
|
||
; the low bit set, just for clarity.
|
||
|
||
ptchPMgrError JMPRom RomPMgrFinalError
|
||
|
||
pMgrProcs
|
||
switch00 DcRom RomEntry2Index
|
||
switch01 DcRom RomIndex2Entries
|
||
|
||
switch02 DC.L RestoreDeviceClut-pMgrProcs+1
|
||
switch03 DC.L ptchResizePalette-pMgrProcs+1
|
||
switch04 DC.L ptchZapLinks-pMgrProcs+1
|
||
switch05 DC.L WhatPal-pMgrProcs+1
|
||
|
||
switch06 DC.L ptchPMgrError-pMgrProcs+1 ; Some unused dispatchs
|
||
switch07 DC.L ptchPMgrError-pMgrProcs+1
|
||
switch08 DC.L ptchPMgrError-pMgrProcs+1
|
||
switch09 DC.L ptchPMgrError-pMgrProcs+1
|
||
|
||
switch10 DcRom RomDeltaRGB
|
||
switch11 DcRom RomNewHiliteColor
|
||
switch12 DC.L ptchPMgrExit-pMgrProcs+1
|
||
switch13 DcRom RomSaveFore
|
||
switch14 DcRom RomSaveBack
|
||
switch15 DcRom RomRestoreFore
|
||
switch16 DcRom RomRestoreBack
|
||
switch17 DcRom RomReinstantiateColors
|
||
switch18 DC.L ReleaseList-pMgrProcs+1
|
||
switch19 DC.L SetDepth-pMgrProcs+1
|
||
switch20 DC.L HasDepth-pMgrProcs+1
|
||
switch21 DC.L PMgrVersion-pMgrProcs+1
|
||
switch22 DC.L SetPaletteUpdates-pMgrProcs+1
|
||
switch23 DC.L GetPaletteUpdates-pMgrProcs+1
|
||
switch24 DC.L CheckColors-pMgrProcs+1
|
||
switch25 DC.L GetGray-pMgrProcs+1
|
||
pMgrProcsEnd
|
||
|
||
|
||
ptchPMgrDispatch
|
||
CMP.B #(PMgrProcsEnd-PMgrProcs)/4,D0
|
||
BHS.S ptchPMgrError ; Too high a dispatch
|
||
MOVE.L A0,-(SP) ; Preserve A0
|
||
LEA pMgrProcs,A0 ; A0->absolute table of dispatchs
|
||
AND #$00FF,D0 ; Kill arg count from dispatch
|
||
MOVE.L (A0,D0*4),-(SP) ; Push target as return address
|
||
MOVE.L 4(SP),A0 ; Restore A0
|
||
RTD #4 ; And go to routine.
|
||
|
||
ENDPROC ; <107>
|
||
|
||
;--- This equate must be kept outside of code/data modules --- ; <107>
|
||
pMgrProcsSize EQU pMgrProcsEnd-pMgrProcs ; <107>
|
||
|
||
|
||
;-------------- Start of GetNewCWindow patch added by KON 10Nov89 --------------------
|
||
|
||
ptchGetNewCWindow PROC EXPORT
|
||
RomGetNewCWindow EQU $21c90
|
||
;
|
||
; First we call the existing routine to get a CWindow. Then we add a palette if one
|
||
; with the same ID exists in the resource file.
|
||
;
|
||
result EQU 18 ; parameter equates
|
||
winID EQU 16
|
||
wStor EQU 12
|
||
behind EQU 8
|
||
|
||
link a6, #0 ;no local parameters <10Nov89 KON>
|
||
clr.l -(sp) ;room for result from ROM GetNewCWindow <10Nov89 KON>
|
||
move.w winID(a6),-(sp) ;do same call as requested <10Nov89 KON>
|
||
move.l wStor(a6),-(sp)
|
||
move.l behind(a6),-(sp)
|
||
JSRRom RomGetNewCWindow ;call the old one <10Nov89 KON>
|
||
move.l (sp)+,result(a6) ;return result <10Nov89 KON>
|
||
;
|
||
; Check if palette with same ID as window exists (taken from getmgr.a)
|
||
;
|
||
clr.l -(sp) ; make room for palette handle <erich>
|
||
move winID(a6),-(SP) ; push window ID <erich>
|
||
_GetNewPalette ; fetchez la palette <erich>
|
||
move.l (sp)+,d0 ; well? <erich>
|
||
|
||
beq.s NoWindowPltt ; sorry, no automatic palette today AWC.PB459
|
||
move.l D0,A0 ; get the palette AWC.PB459
|
||
move.l (A0),A0 ; dereference it AWC.PB459
|
||
move PmPrivate(A0),D1 ; grab the update bits AWC.PB459
|
||
lsr #1,D1 ; put them in position AWC.PB459
|
||
bset #NNewBit,D1 ; use the new CUpdates format AWC.PB459
|
||
bset #DisposeBit,PmPrivate(A0) ; set for automatic disposal AWC.PB459
|
||
|
||
move.l result(a6),-(sp) ; push the window <10Nov89 KON>
|
||
move.l d0,-(sp) ; push the palette <erich>
|
||
move D1,-(sp) ; push cUpdates AWC.PB459
|
||
_SetPalette ; <erich>
|
||
|
||
NoWindowPltt ; AWC.PB459
|
||
unlk a6
|
||
move.l (sp)+,a0 ;return address
|
||
add #10,sp ;strip parameters, leave result
|
||
jmp (a0)
|
||
ENDPROC
|
||
|
||
;-------------- End of GetNewCWindow patch added by KON 10Nov89 ----------------------
|
||
|
||
|
||
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
||
;********************** End Of PaletteMgr Patches? ************************
|
||
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
||
|
||
|
||
;____________________________________________________________________________ DAF <2.6>
|
||
; Window manager patch
|
||
;
|
||
; This patch corrects a bug in SetWin/CtlColor in 32-bit addressing mode. These routines
|
||
; (which operate on identical data structures) can accept a colortable whose ctSize=-1
|
||
; which allows an application to specify that the wcTable be set to the default color
|
||
; set (via a copy of the color table handle). In 32-bit mode it is important that there
|
||
; be exactly one auxWinRec per window. This routine has a bug where -1 color tables can
|
||
; cause extra auxWinRecs to be allocated in 32-bit mode.
|
||
;
|
||
|
||
;
|
||
; procedure SetWinColor ( theWindow:windowPtr; newColorTable:CTabHandle );
|
||
;
|
||
; This procedure changes the awCTable field of the theWindow's auxWinRec.
|
||
; If newColorTable is equal to the default record's CTabHandle, then
|
||
; the auxWinRec is deallocated. If this window does not have an
|
||
; auxWinRec, then one is allocated at the head of the list. If theWindow
|
||
; is NIL, then the default colors are changed. If a record gets deallocated,
|
||
; it's colorTable is disposed unless it has it's resource bit set (then the
|
||
; app must take responsibility)
|
||
;
|
||
; Most of this code is shared with the control manager. Since the auxRec
|
||
; offsets are the same for both types of auxrecs, the code should be OK,
|
||
; even though the code uses the auxWinRec names.
|
||
;
|
||
|
||
NewSetWinColor PROC EXPORT
|
||
EXPORT NewSetCtlColor
|
||
|
||
ROMSetWinColorAfterSetGutsCall EQU $19744
|
||
ROMSetCtlColorAfterSetGutsCall EQU $1979C
|
||
ROMGetAuxGuts EQU $19888 ; GetAuxGuts in Aurora ROM
|
||
ROMSetGutsAfterSpecAlloc32Call EQU $197F6
|
||
ROMDeAlAux EQU $1983A
|
||
ROMSpecAlloc EQU $1981A
|
||
ROMSWCDone EQU $19816
|
||
|
||
MOVEM.L A2/A3,-(SP) ;get some address registers
|
||
MOVE.L AuxWinHead,A2 ;get the list head
|
||
LEA AuxWinHead,A3 ;in case we need to deallocate
|
||
BSR.S SetGuts ;bsr so that we can redraw on return
|
||
JMPROM ROMSetWinColorAfterSetGutsCall
|
||
|
||
NewSetCtlColor
|
||
MOVEM.L A2/A3,-(SP) ;get some address registers
|
||
MOVE.L AuxCtlHead,A2 ;get the list head
|
||
LEA AuxCtlHead,A3 ;in case we need to deallocate
|
||
BSR.S SetGuts ;
|
||
JMPROM ROMSetCtlColorAfterSetGutsCall
|
||
|
||
SetGuts
|
||
|
||
tWind EQU $18 ;some equates for parameters
|
||
nCTab EQU $14 ; after LINK (don't forget the movem above!)
|
||
|
||
LINK A6,#0 ;no globals
|
||
CLR.L -(SP) ;return AuxWinHandle here
|
||
CLR.W -(SP) ;function return here
|
||
CLR.L -(SP) ;NIL for default
|
||
PEA 6(SP) ;pointer to the placeholder
|
||
MOVE.L A2,A1 ;set up list head for GetAuxGuts
|
||
JSRROM ROMGetAuxGuts ;get the default record
|
||
ADDQ #2,SP ;ignore boolean result
|
||
MOVE.L (SP)+,A0 ;get the default handle
|
||
MOVE.L (A0),A0 ;get a pointer
|
||
MOVE.L awCTable(A0),A0 ;get the cTabHandle
|
||
CMP.L nCTab(A6),A0 ;if the same then deallocate
|
||
BEQ DeAlAux ;
|
||
CMP.L #-1,nCTab(A6) ;if -1, then allocate a rec with default table
|
||
BEQ.S SpecAlloc ;
|
||
MOVE.L A0,-(SP) ;save a reg (yuck, but registers are tight!)
|
||
MOVE.L nCTab(A6),A0 ;get the new color table handle
|
||
MOVE.L (A0),A0 ;get a pointer
|
||
CMP.W #-1,ctSize(A0) ;is ctSize -1?
|
||
MOVE.L (SP)+,A0 ;get the register back (don't change flags)
|
||
BEQ.S SpecAlloc32 ;If so, alloc a rec with default table
|
||
JMPROM ROMSetGutsAfterSpecAlloc32Call
|
||
|
||
DeAlAux JMPROM ROMDeAlAux
|
||
SpecAlloc JMPROM ROMSpecAlloc
|
||
|
||
; if this routine is called in 24-bit mode, then it falls through to SpecAlloc and makes
|
||
; a new auxWinRec with a copy of the default colortable. If it is called in 32-bit
|
||
; mode, then it finds the window's pre-existing auxWinRec (one is always guaranteed to
|
||
; exist) and sets it's colortable to be a copy of the default colortable handle.
|
||
|
||
SpecAlloc32
|
||
|
||
TST.B MMU32Bit ; are we in 32-bit mode?
|
||
BEQ.S SpecAlloc ; no, so allocate a new record with a copy of the default colors
|
||
MOVE.L A0,nCTab(A6) ; stick the default colors in the stack frame
|
||
CLR.L -(SP) ; return AuxWinHandle here
|
||
CLR.W -(SP) ; leave room for return value here
|
||
MOVE.L tWind(A6),-(SP) ; find this window
|
||
PEA 6(SP) ; point to placeholder
|
||
MOVE.L A2,A1 ; set up list head for GetAuxGuts (windows or controls)
|
||
JSRROM ROMGetAuxGuts ; get it (it will always be here in 32-bit mode)
|
||
ADDQ #2,SP ; the result should have always returned true
|
||
MOVE.L (SP)+,A0 ; get the win/ctl rec handle>
|
||
MOVE.L (A0),A0 ; get a pointer
|
||
MOVE.L nCTab(A6),awCTable(A0) ;and set the default colortable (in nCTab) field
|
||
JMPROM ROMSWCDone
|
||
|
||
|
||
;____________________________________________________________________________ GGD <2.7>
|
||
; Slot interrupt patch for _sIntInstall
|
||
;
|
||
; <2.2/2.7> Slot Interrupt patch: patches _SIntInstall, and reverses Slot
|
||
; interrupt queue order
|
||
;
|
||
; Change the treatment of Equal Priorities to match the Mac II, which ran the most
|
||
; recently installed element soonest when priorities were equal. This code matches
|
||
; Inside Mac Vol 5, and treats $FF as highest priority. The Mac II has a bug and
|
||
; treats $FF as LOWEST priority within the slot, but as HIGHEST priority across slots.
|
||
; Most cards seemed to beleive the documentation, and none have multiple handlers per slot,
|
||
; One developer figured out that the Mac II was backwards within the slot, and wanted to
|
||
; insert an element ahead of a priority zero (highest with Mac II bug) element. To do
|
||
; this, he took advantage of the was that equal priorities were treated on the Mac II,
|
||
; which is why we are now patching this to match.
|
||
;
|
||
|
||
SIntCorePtch proc export
|
||
WITH SlotIntQElement,slotIntGlobals
|
||
|
||
EXPORT SIntINSTALL
|
||
|
||
ROMGetSlotIntQHead equ $00006E30 ; offset to GetSlotIntQHead
|
||
|
||
;_______________________________________________________________________
|
||
;
|
||
; Routine: SIntINSTALL
|
||
;
|
||
; Arguments: D0 (input) : slot number for routine ($0..$E possible)
|
||
; A0 (input) : ptr to queue element
|
||
; D0 (output): error code - 0 no error
|
||
;
|
||
; Function: Installs a slot interrupt poll routine which is called when
|
||
; a slot interrupt occurs. The queue element is installed in
|
||
; in priority order, $FF highest (first), $00 lowest (last).
|
||
;
|
||
; When elements with EQUAL priorities exist, the most recently
|
||
; installed one is run sooner.
|
||
;
|
||
; <2.7> changes the treatment of Equal priorities to match Mac II.
|
||
;
|
||
; Only low byte of priority word is used (0-255 range).
|
||
; Priorities 200-255 are reserved by Apple.]
|
||
;
|
||
; The Mac II used to maintain priority across slots, which was
|
||
; used when multiple slots interrupted AT THE SAME TIME.
|
||
; We no longer support this, and prioritize by slot number instead.
|
||
; This will be removed from the Mac II in system 7.0
|
||
;
|
||
; The Mac II had a bug in SIntInstall, which had $FF as the highest
|
||
; priority across slots, but had $FF as the lowest within a slot.
|
||
; Most cards used the priority order as documented, ($FF highest), so
|
||
; we will retain that ordering.
|
||
; This will be fixed in the Mac II in System 7.0.
|
||
;
|
||
; Registers Used: D0,D1,D2,A0,A1
|
||
;_______________________________________________________________________
|
||
|
||
SIntINSTALL JsrROM ROMGetSlotIntQHead ; a1 := pointer to qheader
|
||
move.b SQPrio+1(a0),d0 ; get the priority (low byte of word)
|
||
move.w sr,-(sp) ; save interrupt level
|
||
ori.w #HiIntMask,sr ; disable interrupts
|
||
@PrioritySearch
|
||
move.l SQLink(a1),d1 ; get next queue element to check
|
||
beq.s @insert ; if end of list, insert before this
|
||
exg.l a1,d1 ; swap previous and current pointers
|
||
cmp.b SQPrio+1(a1),d0 ; compare priorities
|
||
blo.s @PrioritySearch ; loop until lower priority found (was BLS.S) <2.7>
|
||
; if equal, insert newer in front of older <2.7>
|
||
exg.l d1,a1 ; a1 points to previous, d1 points to current
|
||
@insert ; insert before the lower priority element
|
||
move.l d1,SQLink(a0) ; remainder of queue goes after new element
|
||
move.l a0,SQLink(a1) ; new element goes after previous element
|
||
move.w (sp)+,sr ; restore interrupt level
|
||
moveq.l #noErr,d0 ; return success
|
||
rts ; all done
|
||
|
||
ENDP
|
||
|
||
;____________________________________________________________________________ <20>
|
||
; Patches to Gestalt Functions
|
||
;____________________________________________________________________________
|
||
; The following gestalt selectors are patched or added in this file:
|
||
; - gestaltHardwareAttr
|
||
; - gestaltParityAttr
|
||
; - gestaltMiscAttr
|
||
; - gestaltVersion
|
||
; - gesaltNotificationMgrAttr
|
||
; - gestaltQuickdrawVersion
|
||
; - gestaltAddressingModeAttr
|
||
; - gestaltNuBusConnectors <95>
|
||
; - gestaltSerialAttr <95>
|
||
;
|
||
; The following gestalt selectors are removed in this file:
|
||
; - gestaltRBVAddr
|
||
; - gestaltSCCReadAddr
|
||
; - gestaltSCCWriteAddr
|
||
; - gestaltVIA1Addr
|
||
; - gestaltVIA2Addr
|
||
; - gestaltSlotAttr <95>
|
||
; - gestaltFirstSlot <95>
|
||
; - gestaltSlotCount <95>
|
||
;
|
||
|
||
|
||
|
||
;-----------------------------------------------------------------------------------------
|
||
;
|
||
; Record to describe gestalt function parameters
|
||
;
|
||
;-----------------------------------------------------------------------------------------
|
||
|
||
gestaltParmFrame record {oldA6},decrement
|
||
result ds.w 1 ; OSErr
|
||
argSize equ *-8
|
||
gestaltSelector ds.l 1 ; packed array [1..4] of char
|
||
gestaltResult ds.l 1 ; addr of longint result
|
||
return ds.l 1
|
||
oldA6 ds.l 1
|
||
localFrame equ *
|
||
endR
|
||
|
||
|
||
|
||
|
||
;____________________________________________________________________________ CCH <8>
|
||
; Gestalt function to effectively remove a selector
|
||
;
|
||
; The following is a gestalt function that will return an error as if the
|
||
; selector were undefined.
|
||
;
|
||
; Routine gestaltUndef (
|
||
; gestaltSelector: OSType; = PACKED ARRAY [1..4] OF CHAR;
|
||
; VAR gestaltResult: Longint;
|
||
; ): OSErr; = Integer;
|
||
;
|
||
|
||
gestaltUndef PROC EXPORT
|
||
|
||
with gestaltParmFrame
|
||
link a6,#localFrame
|
||
|
||
move.w #gestaltUndefSelectorErr,result(a6) ; return an error
|
||
|
||
unlk a6
|
||
move.l (sp)+,a0 ; get return value
|
||
add.l #argSize,sp ; restore stack pointer
|
||
jmp (a0) ; return
|
||
|
||
ENDP
|
||
|
||
|
||
;____________________________________________________________________________ CCH <10>
|
||
; Gestalt function for gestaltMiscAttr
|
||
;
|
||
; The following is a patch to the gestaltMiscAttr selector. It returns
|
||
; miscellaneous information about things.
|
||
;
|
||
; Routine gestaltMisc (
|
||
; gestaltSelector: OSType; = PACKED ARRAY [1..4] OF CHAR;
|
||
; VAR gestaltResult: Longint;
|
||
; ): OSErr; = Integer;
|
||
;
|
||
|
||
UserDelayTrap EQU $A84C ; user delay trap <17>
|
||
|
||
gestaltMisc PROC EXPORT
|
||
|
||
with gestaltParmFrame
|
||
link a6,#localFrame
|
||
|
||
clr.l d3 ; clear result
|
||
@hasBootGlobs bset #gestaltBootGlobals,d3 ; we have boot globals
|
||
|
||
@userDelay move.w #UnimplementedTrap,D0 ; get loc of unimplemented trap <58>
|
||
_GetTrapAddress ,newTool ; get the address into A0
|
||
Move.l A0,D2 ; save it for a sec
|
||
Move.l #UserDelayTrap,D0 ; trap ID to check for scrolling throttle
|
||
_GetTrapAddress ,newTool ; get the address of it
|
||
cmp.l a0,d2 ; is it unimplemented?
|
||
beq.s @squareMenus ; nope.. <58>
|
||
bset #gestaltScrollingThrottle,d3 ; <58>
|
||
|
||
@squareMenus move.b NTSC,d0 ; get a copy of the NTSC byte <58>
|
||
andi.b #$0F,d0 ; only look at bottom nibble <58>
|
||
bne.s @next ; if it's non-zero, menus aren't square <58>
|
||
bset #gestaltSquareMenuBar,d3 ; otherwise, it is! <58>
|
||
|
||
@next
|
||
move.l d3,d0 ; put result into d0 <58>
|
||
|
||
move.l gestaltResult(a6),a0 ; get address to place result
|
||
move.l d0,(a0) ;
|
||
move.w #noErr,result(a6) ; return no error
|
||
|
||
unlk a6
|
||
move.l (sp)+,a0 ; get return value
|
||
add.l #argSize,sp ; restore stack pointer
|
||
jmp (a0) ; return
|
||
|
||
ENDP
|
||
|
||
|
||
;____________________________________________________________________________ CCH <20>
|
||
; Gestalt function for gestaltNotificationMgrAttr
|
||
;
|
||
; The following is a patch to the gestaltNotificationMgrAttr selector.
|
||
; It indicates existence of the notification manager trap.
|
||
;
|
||
; Routine gestaltNMgr (
|
||
; gestaltSelector: OSType; = PACKED ARRAY [1..4] OF CHAR;
|
||
; VAR gestaltResult: Longint;
|
||
; ): OSErr; = Integer;
|
||
;
|
||
NMInstallTrap EQU $A05E ; notification manager install trap <20>
|
||
|
||
|
||
gestaltNMgr PROC EXPORT
|
||
|
||
with gestaltParmFrame
|
||
link a6,#localFrame
|
||
|
||
clr.l d0 ; clear result
|
||
Move.w #UnimplementedTrap,D0 ; get loc of unimplemented trap
|
||
_GetTrapAddress ,newTool ; get the address into A0
|
||
Move.l A0,D2 ; save it for a sec
|
||
Move.l #NMInstallTrap,D0 ; trap ID to check for notification mgr
|
||
_GetTrapAddress ,newTool ; get the address of it
|
||
Cmp.l A0,D2 ; is it unimplemented?
|
||
Beq.s @noNMgr ; it is?!
|
||
bset #gestaltNotificationPresent,d0 ; otherwise it exists
|
||
|
||
@noNMgr move.l gestaltResult(a6),a0 ; get address to place result
|
||
move.l d0,(a0) ;
|
||
move.w #noErr,result(a6) ; return no error
|
||
|
||
unlk a6
|
||
move.l (sp)+,a0 ; get return value
|
||
add.l #argSize,sp ; restore stack pointer
|
||
jmp (a0) ; return
|
||
|
||
ENDP
|
||
|
||
|
||
;____________________________________________________________________________ CCH <8>
|
||
; Gestalt function for gestaltVersion
|
||
;
|
||
; The following is a patch to the gestaltVersion selector. It returns the
|
||
; correct version number.
|
||
;
|
||
; Routine getGestaltVers (
|
||
; gestaltSelector: OSType; = PACKED ARRAY [1..4] OF CHAR;
|
||
; VAR gestaltResult: Longint;
|
||
; ): OSErr; = Integer;
|
||
;
|
||
|
||
getGestaltVers PROC EXPORT
|
||
|
||
with gestaltParmFrame
|
||
link a6,#localFrame
|
||
|
||
move.l gestaltResult(a6),a0 ; get address to place result
|
||
move.l #1,(a0) ; return response determined at install time
|
||
move.w #noErr,result(a6) ; return no error
|
||
|
||
unlk a6
|
||
move.l (sp)+,a0 ; get return value
|
||
add.l #argSize,sp ; restore stack pointer
|
||
jmp (a0) ; return
|
||
|
||
ENDP
|
||
|
||
|
||
;____________________________________________________________________________ jwk <95>
|
||
; Gestalt function for gestaltNuBusConnectors
|
||
;
|
||
; The following returns a bitmap of slots with NuBus connectors.
|
||
;
|
||
|
||
gestaltNBCon PROC EXPORT
|
||
|
||
MaxSlots EQU 16 ; max number of slots possible
|
||
|
||
with gestaltParmFrame, NuBusInfo, ProductInfo
|
||
link a6,#localFrame
|
||
movea.l UnivInfoPtr,a0 ; get universal info ptr
|
||
adda.l NuBusInfoPtr(a0),a0 ; add in offset to NuBus info
|
||
clr.l d0 ; clear index
|
||
clr.l d1 ; clear bitmap of NuBus connectors
|
||
@slotLoop btst #hasConnector,(a0,d0.w) ; does this slot have a connector?
|
||
beq.s @next ; if not, go look at next slot
|
||
bset.l d0,d1 ; note that this slot has a NuBus connector
|
||
@next addq #1,d0 ; bump up to next slot
|
||
cmpi.l #MaxSlots,d0 ; have we gone through all slots?
|
||
bne.s @slotLoop ; if not, keep going
|
||
|
||
move.l gestaltResult(a6),a0 ; get address to place result
|
||
move.l d1,(a0) ; return the bitmap of NuBus connectors
|
||
move.w #noErr,result(a6) ; return no error
|
||
|
||
unlk a6
|
||
move.l (sp)+,a0 ; get return value
|
||
add.l #argSize,sp ; restore stack pointer
|
||
jmp (a0) ; return
|
||
|
||
ENDP
|
||
|
||
;____________________________________________________________________________ EH <95>
|
||
; Gestalt function for gestaltSerialAttr
|
||
;
|
||
; The following is a patch to the gestaltSerialAttr selector.
|
||
; It indicates existence of serial attributes on the machine.
|
||
;
|
||
|
||
gestaltSerial PROC EXPORT
|
||
|
||
with gestaltParmFrame,ExpandMemRec,GestaltGlobals
|
||
link a6,#localFrame
|
||
|
||
movea.l ExpandMem,a0 ; get ptr to expandmem rec
|
||
movea.l emGestalt(a0),a0 ; get gestalt global ptr
|
||
moveq.l #0,d0 ; assume no GPI connections
|
||
cmpi.w #gestaltMacLC,machType(a0) ; <107> use real machine name now...
|
||
beq.s @noGPI
|
||
; IIci and IIsi have GPI connected
|
||
moveq.l #(1<<gestaltHasGPIaToDCDa)|\ ; GPIa connected to DCDa
|
||
(1<<gestaltHasGPIaToRTxCa)|\ ; GPIa connected to RTxCa clock input)
|
||
(1<<gestaltHasGPIbToDCDb),d0 ; GPIb connected to DCDb
|
||
|
||
@noGPI move.l gestaltResult(a6),a0 ; get address to place result
|
||
move.l d0,(a0) ;
|
||
move.w #noErr,result(a6) ; return no error
|
||
|
||
unlk a6
|
||
move.l (sp)+,a0 ; get return value
|
||
add.l #argSize,sp ; restore stack pointer
|
||
jmp (a0) ; return
|
||
|
||
ENDP
|
||
|
||
;____________________________________________________________________________ CCH <8>
|
||
; Gestalt function for gestaltParityAttr
|
||
;
|
||
; The following is a patch to the gestaltParityAttr selector. It correctly
|
||
; handles parity on Zone 5, as well as the IIci.
|
||
;
|
||
; Routine gestaltParity (
|
||
; gestaltSelector: OSType; = PACKED ARRAY [1..4] OF CHAR;
|
||
; VAR gestaltResult: Longint;
|
||
; ): OSErr; = Integer;
|
||
;
|
||
|
||
gestaltParity PROC EXPORT
|
||
EXPORT parityValue
|
||
|
||
with gestaltParmFrame
|
||
link a6,#localFrame
|
||
|
||
move.l gestaltResult(a6),a0 ; get address to place result
|
||
move.l parityValue,(a0) ; return response determined at install time
|
||
move.w #noErr,result(a6) ; return no error
|
||
|
||
unlk a6
|
||
move.l (sp)+,a0 ; get return value
|
||
add.l #argSize,sp ; restore stack pointer
|
||
jmp (a0) ; return
|
||
|
||
parityValue dc.l 0 ; response for parity selector
|
||
|
||
ENDP
|
||
|
||
|
||
;____________________________________________________________________________ CCH <3.2>
|
||
; Gestalt function for gestaltQuickdrawVersion
|
||
;
|
||
; The following is a patch to the gestaltQuickdrawVersion selector.
|
||
;
|
||
; Routine gestaltQDVers (
|
||
; gestaltSelector: OSType; = PACKED ARRAY [1..4] OF CHAR;
|
||
; VAR gestaltResult: Longint;
|
||
; ): OSErr; = Integer;
|
||
;
|
||
|
||
gestaltQDVers PROC EXPORT
|
||
|
||
with gestaltParmFrame
|
||
link a6,#localFrame
|
||
|
||
clr.l -(sp) ;make room for result
|
||
_OffScreenVersion
|
||
move.l gestaltResult(a6),a0 ; get address to place result
|
||
move.l (sp)+, d0 ; get QD version from GWorld
|
||
add.w #$100, d0
|
||
|
||
move.l d0, (a0) ; return version number for ci
|
||
move.w #noErr,result(a6) ; return no error
|
||
|
||
unlk a6
|
||
move.l (sp)+,a0 ; get return value
|
||
add.l #argSize,sp ; restore stack pointer
|
||
jmp (a0) ; return
|
||
|
||
ENDP
|
||
|
||
|
||
;____________________________________________________________________________ CCH <6.9>
|
||
; Gestalt function for gestaltAddressingModeAttr
|
||
;
|
||
; The following is a patch to the gestaltAddressingModeAttr selector to add the
|
||
; gestalt32BitCapable bit to this selector.
|
||
;
|
||
; Routine gestaltAddrMode (
|
||
; gestaltSelector: OSType; = PACKED ARRAY [1..4] OF CHAR;
|
||
; VAR gestaltResult: Longint;
|
||
; ): OSErr; = Integer;
|
||
;
|
||
|
||
gestaltAddrMode PROC EXPORT
|
||
|
||
with gestaltParmFrame
|
||
link a6,#localFrame
|
||
|
||
clr.l d0 ; clear result value <6.9>
|
||
move.b SystemInfo,d0 ; get status byte into d1 <6.9>
|
||
not.b d0 ; invert status bits <6.9>
|
||
and.l #3,d0 ; only want bit 0 and bit 1 <6.9>
|
||
bset #gestalt32BitCapable,d0 ; return that ROM is 32-bit clean <6.9>
|
||
move.l gestaltResult(a6),a0 ; get address to place result
|
||
move.l d0,(a0) ; save result <6.9>
|
||
move.w #noErr,result(a6) ; return no error
|
||
|
||
unlk a6
|
||
move.l (sp)+,a0 ; get return value
|
||
add.l #argSize,sp ; restore stack pointer
|
||
jmp (a0) ; return
|
||
|
||
ENDP
|
||
|
||
|
||
IF doScriptMgrGestalt AND (NOT installScriptMgrPtch27) THEN ; <6.1><50>
|
||
;____________________________________________________________________________ pke <2.5>
|
||
; Gestalt function for Script Mgr <08/05/89 pke>
|
||
;
|
||
; The following Gestalt Function is an interface between the Gestalt mechanism
|
||
; and the Script Manager's GetEnvirons routine. Currently, it only supports two
|
||
; Gestalt selectors: gestaltScriptMgrVersion and gestaltScriptCount.
|
||
;
|
||
; Routine gestaltScriptMgr (
|
||
; gestaltSelector: OSType; = PACKED ARRAY [1..4] OF CHAR;
|
||
; VAR gestaltResult: Longint;
|
||
; ): OSErr; = Integer;
|
||
;
|
||
; <08/05/89 pke> New today
|
||
;
|
||
|
||
|
||
gestaltScriptMgr proc export
|
||
|
||
export gestaltSMgrTable ; table for installation <8/05/89 pke>
|
||
|
||
|
||
with gestaltParmFrame ; <3.2>
|
||
link a6,#localFrame
|
||
|
||
; initialize loop, set up default return values
|
||
move.l gestaltSelector(a6),d0 ; selector value
|
||
;; move.l gestaltResult(a6),a0 ; addr for result
|
||
;; clr.l (a0) ; initially set result to 0
|
||
move.l #gestaltUndefSelectorErr,result(a6) ; assume unknown selector
|
||
lea gestaltSMgrTable,a1
|
||
|
||
; loop to find Gestalt selector in table
|
||
@gestaltLoop
|
||
move.l (a1)+,d1 ; get next table entry
|
||
beq.s @gestaltDone ; end of list, quit
|
||
move.w (a1)+,d2 ; now get GetEnvirons verb
|
||
cmp.l d0,d1 ; is selector correct?
|
||
bne.s @gestaltLoop ; no, get next one
|
||
|
||
; ok, we found the Gestalt selector. Now call GetEnvirons with correct verb
|
||
clr.l -(sp) ; space for result
|
||
move.w d2,-(sp) ; push verb
|
||
_GetEnvirons
|
||
move.l gestaltResult(a6),a0 ; addr for result
|
||
move.l (sp)+,(a0) ; pop result into Gestalt
|
||
move.w #noErr,result(a6) ; return no error
|
||
; all done
|
||
@gestaltDone
|
||
|
||
unlk a6
|
||
move.l (sp)+,a0
|
||
add.l #argSize,sp
|
||
jmp (a0)
|
||
|
||
endWith
|
||
|
||
; Table for converting between gestalt selectors and GetEnvirons verbs. Each pair
|
||
; consists of a long with the gestalt selector, followed by a word with the
|
||
; GetEnvirons verb. This table and the equate files where the Gestalt selectors
|
||
; are defined are the only things that need to change to add new Gestalt selectors
|
||
; for the Script Manager.
|
||
|
||
gestaltSMgrTable
|
||
dc.l gestaltScriptMgrVersion
|
||
dc.w smVersion
|
||
|
||
dc.l gestaltScriptCount
|
||
dc.w smEnabled
|
||
|
||
dc.l 0 ; terminator
|
||
|
||
endProc
|
||
ENDIF ; <6.1>
|
||
|
||
|
||
|
||
|
||
|
||
IF NOT SPLINE_FONT THEN ; <6.0.5>
|
||
;____________________________________________________________________________ CEL <5>
|
||
; NewRSect (fixes DrawText)
|
||
;
|
||
; DrText had a check to see if the advance width of a character was zero. If so,
|
||
; it would skip the character. This was bad since International uses zero width
|
||
; characters to lay out certain kanji or vertical text. only one line needed to
|
||
; be taken out. The patch is big but the change is small.
|
||
;
|
||
NewRSect proc export
|
||
;-------------------------------------------
|
||
;
|
||
; KERNED STRIKE FONT FORMAT OFFSETS:
|
||
;
|
||
FORMAT EQU 0 ;WORD
|
||
MINCHAR EQU 2 ;WORD
|
||
MAXCHAR EQU 4 ;WORD
|
||
MAXWD EQU 6 ;WORD
|
||
FBBOX EQU 8 ;WORD fKernMax
|
||
FBBOY EQU 10 ;WORD save as nDescent; unused except as high owTLoc
|
||
FBBDX EQU 12 ;WORD fRectWidth
|
||
FBBDY EQU 14 ;WORD fRectHeight
|
||
LENGTH EQU 16 ;WORD owTLoc
|
||
locASCENT EQU 18 ;WORD Conflict with other Ascent and Descent defines
|
||
locDESCENT EQU 20 ;WORD
|
||
XOFFSET EQU 22 ;WORD leading
|
||
RASTER EQU 24 ;WORD rowWords
|
||
|
||
|
||
;------------------------------------------------------
|
||
;
|
||
; A6 OFFSETS OF PARAMETERS AFTER LINK:
|
||
;
|
||
PARAMSIZE EQU 14 ;SIZE OF PARAMETERS
|
||
COUNT EQU PARAMSIZE+8-2 ;WORD
|
||
TEXTADDR EQU COUNT-4 ;LONG
|
||
NUMER EQU TEXTADDR-4 ;LONG, POINT
|
||
DENOM EQU NUMER-4 ;LONG, POINT
|
||
|
||
|
||
;-----------------------------------------------------------
|
||
;
|
||
; A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
|
||
;
|
||
SAVESTK EQU -4 ;long stack before allocating buffers
|
||
TEXTRECT EQU SAVESTK-8 ;RECT original bounding rect
|
||
TEXTR2 EQU TEXTRECT-8 ;RECT copy of textRext used by maprect
|
||
SRCRECT EQU TEXTR2-8 ;RECT original shadow bounding rect
|
||
DSTRECT EQU SRCRECT-8 ;RECT copy of srcRect used by maprect
|
||
MINRECT EQU DSTRECT-8 ;RECT minimum rect for clipping
|
||
BUFEND EQU MINRECT-4 ;LONG where the offscreen buffer ends
|
||
BUFSIZE EQU BUFEND-2 ;WORD the size of the offscreen buffer
|
||
BUFROW EQU BUFSIZE-2 ;WORD the rowBytes for the offscreen buffer
|
||
BUF2START EQU BUFROW-4 ;LONG second buffer used for shadow
|
||
BUF2END EQU BUF2START-4 ;LONG where shadow buffer ends
|
||
BUFLEFT EQU BUF2END-2 ;WORD output left edge
|
||
HEIGHT EQU BUFLEFT-2 ;WORD font fRectHeight copy
|
||
SRCPTR EQU HEIGHT-4 ;LONG used only in wide character case as temp
|
||
DSTPTR EQU SRCPTR-4 ;LONG used only in wide character case as temp
|
||
BUFSTART EQU DSTPTR-4 ;LONG \ start of bits buffer
|
||
SRCADDR EQU BUFSTART-4 ;LONG >- these 3 grouped: address of font bits
|
||
SRCROW EQU SRCADDR-4 ;LONG / rowbytes of font bits
|
||
maskStart EQU SRCROW-4 ;LONG \ start of mask buffer
|
||
maskAddr EQU maskStart-4 ;LONG >- these 3 grouped: address of mask bits
|
||
mSrcRow EQU maskAddr-4 ;LONG / rowbytes of mask bits
|
||
FROMRECT EQU mSrcRow-8 ;RECT mapRect parameter
|
||
TORECT EQU FROMRECT-8 ;RECT mapRect parameter
|
||
PENLOC EQU TORECT-4 ;POINT copy of original pnLoc
|
||
SPWIDTH EQU PENLOC-4 ;FIXED POINT width of space
|
||
CHARLOC EQU SPWIDTH-4 ;FIXED POINT fractional pen position
|
||
HEIGHTAB EQU CHARLOC-4 ;LONG pointer to font height table
|
||
WIDTAB EQU HEIGHTAB-4 ;LONG pointer to font offset/width table
|
||
LOCTAB EQU WIDTAB-4 ;LONG pointer to font location table
|
||
SAVEA5 EQU LOCTAB-4 ;LONG register saved so can be reused
|
||
characterExtra EQU SAVEA5-4 ;LONG fixed point extra added to each character
|
||
maskBitsPtr EQU characterExtra-4 ;LONG pointer to maskBits, sourcePix, or 0
|
||
bkCol EQU maskBitsPtr-4 ;LONG full of the background color
|
||
leftBack EQU bkCol-4 ;LONG bkCol masked to the left part of the character
|
||
rightBack EQU leftBack-4 ;LONG bkCol masked to the right part of the character
|
||
REALBOUNDS EQU rightBack-4 ;LONG USED FOR SHIELDCURSOR
|
||
leftOffset EQU REALBOUNDS-8 ;2 LONGs offset used by bit field instructions in charblt
|
||
maskSize EQU leftOffset-2 ;WORD size of mask buffer
|
||
mBufRow EQU maskSize-2 ;WORD \ these 2 mask buffer row size
|
||
maskBlts EQU mBufRow-6 ;3 WORDS / grouped: saved state for mask blit
|
||
FAKERGN EQU maskBlts-10 ;RECTANGULAR REGION
|
||
FAKEPTR EQU FAKERGN-4 ;LONG, FAKE MASTER POINTER
|
||
INFO EQU FAKEPTR-8 ;4 WORDS font info record returned by txMeasure (unused)
|
||
NUMER2 EQU INFO-4 ;Point copy of numer for iterative case
|
||
DENOM2 EQU NUMER2-4 ;Point copy of denom for iterative case
|
||
charsRemain EQU DENOM2-2 ;word remaining characters to draw in iterative case
|
||
SRCBITS EQU charsRemain-14 ;bitMap input to shadow stretchBits, bitsToPix
|
||
SRCPIX EQU SRCBITS-(PMREC+CTREC+20) ;pixMap input to normal stretchbits
|
||
maskBits EQU SRCPIX-14 ;bitMap input to bitsToPix for font mask
|
||
DSTPIX EQU maskBits-(PMREC+CTREC+20) ;pixMap destination
|
||
FASTFLAG EQU DSTPIX-1 ;BYTE flag set if source ORing to screen is OK
|
||
maskFont EQU FASTFLAG-1 ;byte flag set if a maskFont is available + requested
|
||
STRETCH EQU maskFont-1 ;BOOLEAN flag set if numerator not equal denominator
|
||
HEIGHTFLAG EQU STRETCH-1 ;byte flag set if font has a height table
|
||
TOPHT EQU HEIGHTFLAG-2 ;word character top & height from font or clip
|
||
MAXMIN EQU TOPHT-2 ;word number of characters in font
|
||
MINCH EQU MAXMIN-2 ;word first character in font
|
||
bitDepth EQU MINCH-2 ;word \ These two bits per pixel in font
|
||
bkCol1 EQU bitDepth-2 ;word / grouped. 1 pixel worth of background color
|
||
italicSlop EQU bkCol1-2 ;word extra width due to italic, bold, outline, shadow
|
||
kernAdjust EQU italicSlop-2 ;word left kerning due to kerning and italic
|
||
penLocHFrac EQU kernAdjust-2 ;word fractional pen position for recursive calls
|
||
longCount EQU penLocHFrac-2 ;word loop counter for doMove
|
||
charWidth EQU longCount-2 ;word width in pixels of current character blt
|
||
stackOffset EQU charWidth-2 ;word 2 if stack was word aligned before link
|
||
countCopy EQU stackOffset-2 ;word copy of character count, decremented as drawn
|
||
CRSRFLAG EQU countCopy-1 ;BYTE set if crsr is shielded (to screen)
|
||
MMUSave EQU CRSRFLAG-1 ;BYTE MMU mode on entry to drawText
|
||
locMode EQU MMUSave-2 ;word copy of text mode, adjusted if arith. + 1 bit
|
||
bitShift EQU locMode-2 ;word how far to shift to multiply by bitDepth
|
||
orNotOK EQU bitShift-1 ;Boolean true if bit extract/insert must be used instead
|
||
notMaskPass EQU orNotOK-1 ;Boolean true if blit is not creating font mask
|
||
textCopyMode EQU notMaskPass-1 ;Boolean true if blit must use extract/insert
|
||
orMode EQU textCopyMode-1 ;Boolean true if mode is srcOr & forecolor is black
|
||
colorSource EQU orMode-1 ;Boolean true if font contains colors (nonblack/white)
|
||
saveHilite EQU colorSource-1 ;byte saved hilite flag for iterative state
|
||
run32bit EQU saveHilite-1 ;byte flag to run 32 bit
|
||
VARSIZE EQU (((run32bit+1)/4)-1)*4 ;SIZE OF VARIABLES long aligned
|
||
|
||
FromDrText EQU $28468
|
||
ROMRSect EQU $2C6D4
|
||
RomIterate EQU $281AA
|
||
|
||
cmpRA FromDrText,(sp) ; is this called from DrText?
|
||
beq.s @doDrTextPatch ; yes, go fix the patch
|
||
jmpROM ROMRSect ; call back to the ROM
|
||
@doDrTextPatch
|
||
ADDQ #4, sp ; Pop off return addr and come back here
|
||
jsrROM ROMRSect ; call back to the ROM
|
||
|
||
;---------------------------------------------------------------------------------------
|
||
; < BELOW COPIED VERBATIM FROM THE ROM UNTIL FURTHER NOTICE >
|
||
;
|
||
BEQ GOHOME ;QUIT IF NO INTERSECTION
|
||
MOVE (SP)+,textR2+right(A6) ;restore text right
|
||
;
|
||
; Test to see if spline:
|
||
; If spline set up clipping variables
|
||
;
|
||
|
||
;
|
||
; Set up srcAddr, srcRow, and height
|
||
;
|
||
LEA 26(A2),a0 ;GET START OF FONT BITMAP
|
||
MOVE.L a0,SRCADDR(A6) ;SAVE FOR LATER
|
||
|
||
MOVEQ #0,D1 ;zero high word
|
||
MOVE RASTER(A2),D1 ;GET WORDS PER ROW IN FONT
|
||
MOVE bitShift(A6),D0
|
||
LSL.L D0,D1 ;scale up font rowWords
|
||
ADD.L D1,D1 ;DOUBLE FOR BYTES PER ROW
|
||
MOVE.L D1,SRCROW(A6) ;REMEMBER FOR LATER
|
||
MOVE FBBDY(A2),HEIGHT(A6) ;SETUP HEIGHT FOR LATER
|
||
;
|
||
; Test for fast case:
|
||
; not stretched, no color mapping, txMode = srcOr, same bits per pixel
|
||
; not bold, italic, underlined, outlined or shadowed,
|
||
; visRgn and clipRgn both rectangular.
|
||
;
|
||
TST.B fmOutItalic(A4) ;TEST BOLD $$$
|
||
BNE NOTFAST ;NOT FAST UNLESS BOTH ZERO
|
||
TST.B fmOutBold(A4) ;TEST BOLD
|
||
BNE NOTFAST ;NOT FAST
|
||
TST.B orMode(A6) ;IS TEXT MODE SRCOR ? (or srcCopy + mask, see above)
|
||
BEQ NOTFAST ;NO, NOT FAST
|
||
TST.W 10(A4) ;TEST ULTHICK AND SHADOW
|
||
BNE NOTFAST ;NOT FAST UNLESS BOTH ZERO
|
||
TST.B STRETCH(A6) ;IS TEXT STRETCHED ?
|
||
BNE NOTFAST ;YES, NOT FAST
|
||
MOVE.L ([CLIPRGN,A3]),A0 ;GET CLIPRGN HANDLE, dereferenced
|
||
MOVEQ #10,D0
|
||
CMP RGNSIZE(A0),D0 ;IS CLIPRGN RECTANGULAR ?
|
||
BNE NOTFAST ;NO, NOT FAST
|
||
MOVEQ #1,D0
|
||
MOVE bitShift(A6),D1 ;get the depth of the source map
|
||
LSL D1,D0 ;turn into 1 ÉÊ8
|
||
CMP DSTPIX+PIXELSIZE(A6),D0 ;same depth per pixel?
|
||
BNE NOTFAST ;=>NOPE
|
||
cmp #16,dstPix+pixelType(A6) ;is it a direct device? @@@@ BAL 16Jun88
|
||
bne.s @modeok
|
||
seq textCopyMode(a6) ;yes, can't go fast for now @@@@ BAL 16Jun88
|
||
clr locmode(a6) ;this essentially alters mode to srcCopy
|
||
bra NotFast
|
||
|
||
@modeok MOVE.L VISRGN(A3),A1 ;GET VISRGN HANDLE
|
||
MOVE.L (A1),A0 ;DE-REFERENCE IT
|
||
CMP #10,RGNSIZE(A0) ;IS VISRGN RECTANGULAR ?
|
||
BEQ.S FAST ;YES, TAKE FAST OPTIMIZATION
|
||
;
|
||
; All systems go except for VisRgn not rectangular.
|
||
; Check if visRgn sect minRect is rectangular.
|
||
; IF TrimRect(visRgn,minRect) THEN take the fast way.
|
||
;
|
||
MOVE.L A1,-(SP) ;PUSH VISRGN
|
||
PEA MINRECT(A6) ;PUSH MINRECT
|
||
MOVE.W #-1,-(SP) ;pass Trim = True
|
||
_TRIMRECT ;CALL TRIMRECT
|
||
BLT GOHOME ;quit if intersection empty
|
||
BGT NOTFAST ;continue if non-rectangular
|
||
;
|
||
; Fast case, go directly to screen.
|
||
; If text is clipped vertically, then clear heightflag and update TOPHT
|
||
;
|
||
FAST
|
||
ST FASTFLAG(A6) ;REMEMBER WE'RE GOING FAST
|
||
CLR.B maskFont(A6) ;no need for second mask pass in fast case
|
||
CLR.L bkCol(A6) ;zero out back color long
|
||
MOVE MINRECT+TOP(A6),D0 ;GET MINRECT.TOP
|
||
MOVE MINRECT+BOTTOM(A6),D1 ;GET MINRECT.BOTTOM
|
||
SUB TEXTRECT+TOP(A6),D0 ;was top clipped ?
|
||
BNE.S VCLIP ;yes, handle clip
|
||
CMP TEXTRECT+BOTTOM(A6),D1 ;was bottom clipped ?
|
||
BEQ.S VCLIPOK ;no, continue
|
||
|
||
VCLIP CLR.B HEIGHTFLAG(A6) ;can't use height table
|
||
MOVE.B D0,TOPHT(A6) ;use adjusted top
|
||
SUB MINRECT+TOP(A6),D1 ;calc clipped height
|
||
MOVE.B D1,TOPHT+1(A6) ;replace TOPHT
|
||
|
||
VCLIPOK MOVE TEXTRECT+TOP(A6),D0 ;GET DST TOP
|
||
SUB DSTPIX+BOUNDS+TOP(A6),D0 ;CONVERT TO GLOBAL COORDINATES
|
||
MOVE DSTPIX+ROWBYTES(A6),D1 ;GET ROWBYTES
|
||
AND #nuRBMask,D1 ;CLEAR OFF FLAG BITS
|
||
MULS D1,D0 ;MULT BY ROWBYTES
|
||
ADD.L DSTPIX+BASEADDR(A6),D0 ;ADD START OF DST BITMAP
|
||
MOVE.L D0,BUFSTART(A6) ;SET UP BUFSTART FOR LATER
|
||
MOVE D1,BUFROW(A6) ;SET UP BUFROW FOR LATER
|
||
MOVE DSTPIX+BOUNDS+LEFT(A6),BUFLEFT(A6) ;REMEMBER BUFLEFT
|
||
|
||
TST.B CRSRFLAG(A6) ;IS DST TO A SCREEN? <BAL 19Sep88>
|
||
BEQ GETPTRS ;=>NO
|
||
PEA MINRECT(A6) ;PUSH SHIELD RECT
|
||
MOVE.L REALBOUNDS(A6),-(SP) ;PUSH DELTA FOR GLOBAL
|
||
_SHIELDCURSOR ;HIDE CURSOR IF IT INTERSECTS
|
||
;-----------------------------------------------------------
|
||
;
|
||
; Clean pointers and then
|
||
; Switch to 32 bit addressing mode
|
||
;
|
||
MOVE.L SRCADDR(A6),d0 ;get 24 bit base addr
|
||
_Translate24To32 ;mask off high byte BAL/MCF 03Dec88
|
||
MOVE.L d0,SRCADDR(A6) ;SAVE FOR LATER
|
||
|
||
move.l a2,d0 ;get FontPtr
|
||
_Translate24To32 ;mask off high byte BAL/MCF 03Dec88
|
||
move.l d0,a2 ;clean font ptr
|
||
|
||
@setMMUMode
|
||
MOVE stackOffset(A6),D1
|
||
MOVE.L TEXTADDR(A6,D1),D0 ;GET TEXTPTR
|
||
_Translate24To32 ;mask off high byte BAL/MCF 03Dec88
|
||
MOVE.L d0,TEXTADDR(A6,D1) ;SAVE FOR LATER
|
||
|
||
moveq #true32b,d0 ;switch to 32 bit addressing
|
||
move.l a2,-(sp) ;save FontPtr
|
||
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
|
||
move.l (sp)+,a2 ;restore FontPtr
|
||
move.b d0,MMUsave(a6) ;save previous state for later
|
||
|
||
MOVE.B #1, run32bit(A6) ; Set flag to state running 32 bit clean
|
||
BRA GETPTRS
|
||
|
||
NOTSCREEN
|
||
;
|
||
; Slow case: Setup for an off-screen buffer.
|
||
;
|
||
; Calc bufLeft: (LONG-align to avoid shift)
|
||
;
|
||
NOTFAST SF FASTFLAG(A6) ;NOT GOING DIRECTLY TO SCREEN
|
||
SF CRSRFLAG(A6) ;CRSR HAS NOT BEEN SHIELDED <BAL 19Sep88>
|
||
MOVE TEXTRECT+LEFT(A6),D0 ;GET TEXTRECT LEFT
|
||
SUB DSTPIX+BOUNDS+LEFT(A6),D0 ;CONVERT TO GLOBAL
|
||
AND #$FFE0,D0 ;TRUNC TO LONG BOUND
|
||
ADD DSTPIX+BOUNDS+LEFT(A6),D0 ;RETURN TO LOCAL COORDS
|
||
MOVE D0,BUFLEFT(A6) ;REMEMBER FOR LATER
|
||
;
|
||
; Calculate buffer size
|
||
;
|
||
MOVEQ #0,D1 ;clear high word
|
||
MOVE TEXTRECT+RIGHT(A6),D1 ;BUFRIGHT := TEXTRECT RIGHT
|
||
SUB D0,D1 ;WIDTH:=BUFRIGHT-BUFLEFT
|
||
MOVE D1,D2 ;mask depth as well
|
||
MOVE bitShift(A6),D4 ;convenient constant
|
||
LSL.L D4,D1 ;scale up by pixel size + 1 for mask
|
||
LSR.L #5,D1 ;CONVERT DOTS TO LONGS
|
||
ADD #2,D1 ;ROUND UP PLUS EXTRA LONG
|
||
MOVE HEIGHT(A6),D3 ;GET HEIGHT
|
||
MULU D1,D3 ;BUFSIZE:=HEIGHT*BUFROW LONGS
|
||
|
||
; if the intermediate result is too big, stop before going any further
|
||
|
||
CMP.L #$1C00,D3 ;is it bigger than 28K? (unit is longs)
|
||
BGT.S DoSubDivide ;if so, draw fewer characters at a time
|
||
MOVE D3,BUFSIZE(A6) ;SAVE FOR LATER
|
||
ADD D1,D3 ;add for stretch srcBuf
|
||
LSL #2,D1 ;QUAD BUFROW FOR BYTES
|
||
MOVE D1,BUFROW(A6) ;SAVE FOR LATER
|
||
MOVE TEXTR2+RIGHT(A6),D5
|
||
SUB TEXTR2+LEFT(A6),D5
|
||
LSR #5,D5 ;convert to longs
|
||
ADDQ #2,D5 ;account for slop
|
||
MOVE D5,D0
|
||
ADD D0,D3 ;in case clip is nonrectangular
|
||
ADD D0,D3 ;in case vis is nonrectangular
|
||
LSL D4,D0 ;scale up by source depth
|
||
ADD D0,D3 ;add stretch destination buffer size
|
||
MULU dstPix+pixelSize(A6),D5 ;size of composite mask
|
||
ADD D5,D3 ;include it
|
||
|
||
;if srcDepth not equal to dstDepth, add stretch dest. buf. again
|
||
|
||
ADD D5,D3 ;include space for scale buffer
|
||
|
||
;set up maskSize, maskRow
|
||
|
||
TST.B maskFont(A6) ;do we need a mask to pass to stretchBits?
|
||
BEQ.S @noMask
|
||
LSR #5,D2 ;CONVERT DOTS TO LONGS
|
||
ADD #2,D2 ;ROUND UP PLUS EXTRA LONG
|
||
ADD D2,D1 ;total number of longs
|
||
MOVE HEIGHT(A6),D0 ;GET HEIGHT
|
||
MULU D2,D0 ;BUFSIZE:=HEIGHT*BUFROW LONGS
|
||
MOVE D0,maskSize(A6) ;SAVE FOR LATER
|
||
LSL #2,D2 ;QUAD BUFROW FOR BYTES
|
||
MOVE D2,mBufRow(A6) ;SAVE FOR LATER
|
||
ADD D0,D3 ;add for stack check calculation
|
||
ADD D2,D3 ;add for stretch srcMaskBuf
|
||
MOVE TEXTR2+RIGHT(A6),D0
|
||
SUB TEXTR2+LEFT(A6),D0
|
||
LSR #5,D0 ;convert from dots to longs
|
||
ADD D0,D3 ;add stretch mask destination buffer size
|
||
@noMask
|
||
|
||
;
|
||
; Calculate total stack requirements for off-screen buffers.
|
||
;
|
||
TST.B 11(A4) ;ARE WE SHADOWING ?
|
||
BEQ.S @1 ;NO, CONTINUE
|
||
ADD bufSize(A6),D3 ;YES, CALC 2*BUFSIZE
|
||
ADD D1,D3 ;add in 4 * source rows for shadow
|
||
@1 LSL.L #2,D3 ;CALC TOTAL STACK BYTES NEEDED
|
||
|
||
; how much slop? size of scale table (256 bytes maximum)
|
||
; size of stretch stack frame (750 bytes for parameters, local stack frame, saved regs),
|
||
; and about 1K for interrupts.
|
||
|
||
ADD.L #2048,D3 ;ADD 2 KBYTE SLOP
|
||
;
|
||
; If stack is too small to allocate buffer(s), then draw half as many characters at a time.
|
||
;
|
||
_StackAvail ;Get StackAvail IN D0
|
||
CMP.L D0,D3 ;IS stackNeeded > stackAvail ?
|
||
BLE.S StackAlmost ;NO, CONTINUE
|
||
|
||
DoSubDivide
|
||
MOVE stackOffset(A6),D6 ;2 if stack was not aligned, otherwise, 0
|
||
MOVE count(A6,D6),D0 ;how many characters to draw
|
||
MOVE D0,D7 ;figure half
|
||
LSR #1,D7
|
||
BNE.S @subDivide ;if more than 1 left, can subdivide problem
|
||
SUBQ #1,charsRemain(A6) ;pretend the one character was drawn
|
||
BRA GoHome ;if only 1 character, punt
|
||
|
||
@subDivide
|
||
; *** look for space character? Could adjust D7 to coincide with a space if any, making
|
||
; *** drawing look better (for italics, kerns)
|
||
|
||
TST charsRemain(A6) ;if zero, this is the first time through
|
||
BNE.S @notFirst
|
||
MOVE.B HiliteMode,saveHilite(A6) ;save original in case stretch is called multiple times
|
||
MOVE D0,charsRemain(A6) ;initialize partial count drawing location
|
||
@notFirst
|
||
MOVE.L PENLOC(A6),PNLOC(A3) ;RESTORE PNLOC TO ORIGINAL
|
||
TST PORTBITS+ROWBYTES(A3) ; is it a new port?
|
||
BPL.S @useOld ; no, no fraction to restore
|
||
MOVE PenLocHFrac(A6),pnLocHFrac(A3) ;restore fraction if applicable
|
||
@useOld
|
||
MOVE D7,count(A6,D6) ;reset count to draw
|
||
doIterate
|
||
MOVE.L grafGlobals(A5),A4 ;set up grafGlobals pointer for getting real width
|
||
MOVE.L numer2(A6),numer(A6,D6) ;restore numerator
|
||
MOVE.L denom2(A6),denom(A6,D6) ;restore denominator
|
||
MOVE.B saveHilite(A6),HiliteMode ;restore hilite bit
|
||
;
|
||
; < ABOVE COPIED VERBATIM FROM THE ROM >
|
||
;---------------------------------------------------------------------------------------
|
||
; JMP Iterate ;draw first half of string
|
||
JMPRom RomIterate ;
|
||
;---------------------------------------------------------------------------------------
|
||
; < BELOW COPIED VERBATIM FROM THE ROM >
|
||
;
|
||
; draw the second half of the string, but drawing no more characters than could be successfully
|
||
; drawn by the first half.
|
||
|
||
secondHalf
|
||
MOVEQ #0,D7 ;zero high word
|
||
MOVE stackOffset(A6),D6 ;2 if stack was not aligned, otherwise, 0
|
||
MOVE count(A6,D6),D7 ;number of characters drawn last
|
||
MOVE charsRemain(A6),D0 ;how many characters remain?
|
||
CMP D0,D7 ;donÕt try to draw more than worked last
|
||
BLE.S @ok
|
||
MOVE D0,count(A6,D6) ;draw what remains for the second half
|
||
@ok
|
||
ADD.L D7,textAddr(A6,D6) ;bump source address by half already drawn
|
||
BRA.S doIterate
|
||
|
||
; ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
||
;
|
||
; Allocate and clear an off-screen buffer
|
||
;
|
||
; If the source font is only 1 bit deep, clear the screen to white. Also, if the transfer
|
||
; mode is xor, bic, or, clear the screen to white. If an arithmetic mode or copy and
|
||
; source is multibits deep, assume depth of source font is equal to destination depth.
|
||
; Also assume that background of buffer must be colored the same as the port background color.
|
||
|
||
StackAlmost
|
||
MOVEQ #0,D0 ;get a long of white
|
||
TST bitShift(A6) ;is source 1 bit?
|
||
BEQ.S @whiteBackCol
|
||
CMP #srcXor,locMode(A6) ;srcXor?
|
||
BEQ.S @whiteBackCol ;even if font contains colors, leave background white
|
||
TST.B colorSource(A6) ;font contains color?
|
||
BNE.S @useBackCol ;if so, must color the buffer
|
||
CMP #$32,locMode(A6) ;hilite?
|
||
BEQ.S @whiteBackCol ;leave background white if so
|
||
BTST #5,locMode+1(A6) ;arithmetic?
|
||
BEQ.S @whiteBackCol ;if copy, or leave background white
|
||
@useBackCol
|
||
SUBQ #6,SP ;allocate VAR RGBColor
|
||
MOVE.L SP,-(SP) ;point to VAR RGBColor
|
||
_GetBackColor ;ask for the background color
|
||
CLR.L -(SP) ;make room for function result
|
||
PEA 4(SP) ;point to VAR RGBColor
|
||
_Color2Index
|
||
MOVEQ #0,D0
|
||
MOVEQ #32,D1 ;
|
||
MOVE bitDepth(A6),D2 ;get destination bits per pixel
|
||
@nxtPixel
|
||
ASL.L D2,D0
|
||
OR.l (SP),D0 ;or in result of color2Index <BAL 04July88>
|
||
SUB D2,D1
|
||
BGT.S @nxtPixel
|
||
ADD #10,SP ;strip RGBColor and long result
|
||
|
||
@whiteBackCol
|
||
MOVE.L D0,bkCol(A6) ;save for comparing with background, later
|
||
|
||
STACKOK MOVE bufSize(A6),D3
|
||
SUBQ #1,D3 ;INIT DBRA LOOP COUNT
|
||
MOVE.L D0,-(SP) ;PAD BUFFER WITH AN EXTRA ZERO
|
||
MOVE.L SP,BUFEND(A6) ;REMEMBER WHERE BUFFER ENDS
|
||
CLRLOOP MOVE.L D0,-(SP)
|
||
DBRA D3,CLRLOOP ;ALLOCATE AND CLEAR BUFFER
|
||
MOVE.L SP,BUFSTART(A6) ;REMEMBER START OF BUFFER
|
||
MOVE.L D0,-(SP) ;PAD BUFFER WITH AN EXTRA ZERO
|
||
|
||
TST.B maskFont(A6)
|
||
BEQ.S @noMask
|
||
MOVE maskSize(A6),D3
|
||
SUBQ #1,D3
|
||
CLR.L -(SP)
|
||
@clrMask
|
||
CLR.L -(SP)
|
||
DBRA D3,@clrMask
|
||
MOVE.L SP,maskStart(A6)
|
||
@noMask
|
||
CLR.L -(SP)
|
||
;
|
||
; Get pointers to location table, width table, and height table in font
|
||
;
|
||
GETPTRS
|
||
LEA 26(A2),A0 ;GET START OF FONT BITMAP
|
||
MOVEQ #0,D0 ;zero high word
|
||
MOVE FBBDY(A2),D0 ;GET HEIGHT OF FONT BITMAP
|
||
MULU.L SRCROW(A6),D0 ;CALC TOTAL SIZE OF STRIKE
|
||
ADD.L D0,A0 ;A1 := START OF LOC TABLE
|
||
MOVE.L A0,LOCTAB(A6) ;SAVE FOR LATER
|
||
|
||
; *** could test bitShift first and only check fNDescent if bitDepth > 1 É
|
||
|
||
MOVE.W fNDescent(A2),D0 ;possibly the high word of owTLoc
|
||
SWAP D0 ;put it in the high word
|
||
BPL.S @notNegative
|
||
MOVEQ #0,D0 ;old fonts have negative of ascent here
|
||
@notNegative
|
||
MOVE LENGTH(A2),D0 ;HOW MANY WORDS IN STRIKE BODY
|
||
LEA 16(A2,D0.L*2),A1 ;GET START OF WIDTH TABLE
|
||
MOVE.L A1,WIDTAB(A6) ;SAVE FOR LATER
|
||
|
||
MOVE MAXCHAR(A2),D0 ;GET MAXCHAR
|
||
MOVE MINCHAR(A2),D1 ;GET MINCHAR
|
||
MOVE D1,MINCH(A6) ;STASH MINCHAR FOR LATER
|
||
SUB D1,D0 ;CALC MAXCHAR-MINCHAR
|
||
MOVE D0,MAXMIN(A6) ;SAVE FOR LATER
|
||
|
||
ADD #3,D0 ;CALC MAXMIN+3
|
||
BTST #1,1(A2) ;DOES FONT HAVE WIDTH TABLE ?
|
||
BEQ.S NOWID ;NO, CONTINUE
|
||
ADD D0,D0 ;SKIP WIDTH TABLE
|
||
NOWID LEA 0(A1,D0*2),A0 ;POINT TO HEIGHT TABLE
|
||
MOVE.L A0,HEIGHTAB(A6) ;SAVE FOR LATER
|
||
|
||
;
|
||
; Set up space width
|
||
;
|
||
MOVE.L widthTabHandle,A0 ;point to width table
|
||
MOVE.L (A0),A0
|
||
MOVE.L 128(A0),SPWIDTH(A6) ;get width of the space char
|
||
;
|
||
; Setup misc stuff in registers for speed
|
||
;
|
||
MOVE BUFLEFT(A6),D1 ;GET BUFLEFT
|
||
MOVE PENLOC+H(A6),D0 ;GET PEN LOCATION
|
||
ADD kernAdjust(A6),D0 ;ADJUST FOR KERNING
|
||
SUB D1,D0 ;MAKE CHARLOC RELATIVE TO BUFLEFT
|
||
MOVE.W D0,CHARLOC(A6) ;INIT INT PART OF CHARLOC
|
||
TST PORTBITS+ROWBYTES(A3) ;is it a new port?
|
||
BPL.S @useOld ;no, set fraction to 1/2
|
||
|
||
MOVE penLocHFrac(A6),CHARLOC+2(A6) ;set up fractional part <PB362> BAL
|
||
BRA.S @goOn
|
||
@useOld
|
||
MOVE #$8000,CHARLOC+2(A6)
|
||
@goOn
|
||
SUB D1,MINRECT+LEFT(A6) ;MAKE MINRECT.LEFT AND
|
||
SUB D1,MINRECT+RIGHT(A6) ;MINRECT.RIGHT BUFFER RELATIVE
|
||
MOVE stackOffset(A6),D0
|
||
MOVE.L TEXTADDR(A6,D0),A1 ;GET TEXTPTR
|
||
BRA.S NEXTCH ;GO TO LOOP START
|
||
|
||
|
||
;---------------------------------------------------
|
||
;
|
||
; Here's the main character drawing loop:
|
||
;
|
||
MISSING
|
||
MOVE MAXMIN(A6),D0 ;NO, USE MISSING SYMBOL
|
||
ADD #1,D0 ;WHICH IS ONE PAST MAXCHAR
|
||
MOVE.L WIDTAB(A6),A0 ;POINT TO WIDTH TABLE
|
||
MOVE 0(A0,D0*2),D3 ;GET OFFSET AND WIDTH BYTES
|
||
CMP #-1,D3 ;missing?
|
||
BNE NOTMISS ;IS MISSING CHAR MISSING ?
|
||
BRA.S NEXTCH ;YES, SKIP THIS CHAR
|
||
|
||
SPACECH MOVE.L SPWIDTH(A6),D1 ;GET SPACE WIDTH
|
||
ADD.L D1,CHARLOC(A6) ;BUMP CHARLOC
|
||
SKIPCH SUB #1,charsRemain(A6) ;decrement total character count
|
||
SUB #1,countCopy(A6) ;decrement partial draw character count
|
||
BLE STRDONE ;QUIT IF CHARCOUNT <= 0
|
||
NEXTCH CLR D0 ;get ready for byte
|
||
MOVE.B (A1)+,D0 ;GET NEXT CHAR
|
||
CMP.B #32,D0 ;IS IT A SPACE ?
|
||
BEQ.S SPACECH ;YES, HANDLE IT
|
||
|
||
MOVE.L WidthTabHandle,A0 ;POINT TO WIDTH TABLE
|
||
MOVE.L (A0),A0
|
||
MOVE D0,D4 ;COPY CHARACTER
|
||
MOVE.L 0(A0,D4*4),D4 ;GET FIXED POINT WIDTH
|
||
ADD.L characterExtra(A6),D4 ;add in character extra, if any
|
||
|
||
;
|
||
; < ABOVE COPIED VERBATIM FROM THE ROM >
|
||
;
|
||
;---------------------------------------------------------------------------------------
|
||
;
|
||
; BLE.S SKIPCH ;SKIP CharBlt if Advance width <= 0 <1.6-11april89-CEL>
|
||
;
|
||
;---------------------------------------------------------------------------------------
|
||
;
|
||
; < BELOW COPIED VERBATIM FROM THE ROM UNTIL FURTHER NOTICE >
|
||
;
|
||
SUB MINCH(A6),D0 ;SUBTRACT SAVED MINCHAR
|
||
CMP MAXMIN(A6),D0 ;IS CH BETWEEN MINCHAR AND MAXCHAR ?
|
||
BHI MISSING ;Missing so skip it
|
||
|
||
OKCHAR MOVE.L WIDTAB(A6),A0 ;POINT TO WIDTH TABLE
|
||
MOVE 0(A0,D0*2),D3 ;GET OFFSET AND WIDTH BYTES
|
||
CMP #-1,D3 ;missing?
|
||
BEQ MISSING ;OFFSET NEG = MISSING CHAR
|
||
|
||
NOTMISS LSR #8,D3 ;GET OFFSET BYTE
|
||
ADD.W CHARLOC(A6),D3 ;DSTLEFT := CHARLOC.INT + OFFSET
|
||
ADD.L D4,CHARLOC(A6) ;ADD FIXED POINT WIDTH TO CHARLOC
|
||
|
||
MOVE.L LOCTAB(A6),A0 ;POINT TO LOCATION TABLE
|
||
MOVEQ #0,D1 ; *** clear top word
|
||
MOVE 0(A0,D0*2),D1 ;GET SRCLEFT
|
||
MOVE 2(A0,D0*2),D2 ;GET SRCRIGHT
|
||
SUB D1,D2 ;CALC WIDTH OF BITS
|
||
BLE SKIPCH ;SKIP CHARBLT IF WIDTH <= 0
|
||
MOVE D2,charWidth(A6) ;save for later
|
||
ADD D3,D2 ;DSTRIGHT := DSTLEFT + WIDTH
|
||
|
||
TST.B HEIGHTFLAG(A6) ;does font have height table ?
|
||
BEQ.S NOHEIGHT ;no, continue
|
||
MOVE.L HEIGHTAB(A6),A0 ;get height table
|
||
MOVE 0(A0,D0*2),TOPHT(A6) ;get this char's top and height
|
||
NOHEIGHT
|
||
|
||
;-----------------------------------------------------------------------
|
||
;
|
||
; Horizontal clip only if FastFlag: (else stretch,outline,shadow,italic die)
|
||
;
|
||
; skip if hidden on left, string done if hidden on right.
|
||
;
|
||
; at this point: D1: srcLeft
|
||
; D2: dstRight
|
||
; D3: dstLeft
|
||
;
|
||
TST.B FastFlag(A6) ;ARE WE GOING FAST ?
|
||
BEQ.S HORIZOK ;NO, DON'T CLIP
|
||
CMP MINRECT+LEFT(A6),D3 ;IS DSTLEFT < MINRECT.LEFT ?
|
||
BGE.S LEFTOK ;NO, CONTINUE
|
||
CMP MINRECT+LEFT(A6),D2 ;IS DSTRIGHT <= MINRECT.LEFT ?
|
||
BLE SKIPCH ;YES, SKIP THIS CHAR
|
||
TRIMLFT MOVE MINRECT+LEFT(A6),D0 ;NO, GET MINRECT.LEFT
|
||
SUB D3,D0 ;DISCARD:=MINRECT.LEFT-DSTLEFT
|
||
ADD D0,D1 ;SRCLEFT:=SRCLEFT+DISCARD
|
||
ADD D0,D3 ;DSTLEFT:=DSTLEFT+DISCARD
|
||
CMP MINRECT+RIGHT(A6),D2 ;IS DSTRIGHT > MINRECT.RIGHT ?
|
||
BLE.S fixCharWidth ;NO, CONTINUE
|
||
BRA.S TRIMRT ;YES, TRIM RIGHT
|
||
LEFTOK CMP MINRECT+RIGHT(A6),D2 ;IS DSTRIGHT <= MINRECT.RIGHT ?
|
||
BLE.S HORIZOK ;YES, CONTINUE
|
||
CMP MINRECT+RIGHT(A6),D3 ;IS DSTLEFT >= MINRECT.RIGHT ?
|
||
BGE STRDONE ;YES, IGNORE REST OF STRING
|
||
TRIMRT MOVE MINRECT+RIGHT(A6),D2 ;NO, TRIM DSTRIGHT
|
||
fixCharWidth
|
||
MOVE D2,D0 ;char width has been trimmed left, right, or both
|
||
SUB D3,D0 ;so recalculate char width to draw
|
||
MOVE D0,charWidth(A6) ;and save this tidbit of info. for later
|
||
HORIZOK
|
||
|
||
;--------------------------------------------------------------
|
||
;
|
||
; Inputs to local block CharBlt:
|
||
;
|
||
; srcAddr(A6)
|
||
; srcRow(A6)
|
||
; bufStart(A6) = dstAddr
|
||
; bufRow(A6) = dstRow
|
||
; D1 = srcLeft
|
||
; D2 = dstRight relative to buffer, > dstLeft
|
||
; D3 = dstLeft relative to buffer
|
||
; TOPHT(A6) top and height
|
||
;
|
||
; CLOBBERS: D0,D1,D2,D3,D4,D5,D6,D7,A0,A2,A3,A4,A5
|
||
; PRESERVES: A1,A6,A7
|
||
;
|
||
;
|
||
; Setup shift count in D5 (relative shift between src and dst)
|
||
;
|
||
|
||
MOVEM D1-D3,maskBlts(A6)
|
||
MOVE.B textCopyMode(A6),orNotOK(A6) ;if copy or if mask mode, do bit moves instead of OR
|
||
|
||
ST notMaskPass(A6) ;use the bitDepth this pass
|
||
MOVE bitShift(A6),D0 ;get font scale factor
|
||
LSL D0,D1
|
||
LSL D0,D2
|
||
LSL D0,D3 ;scale up all three
|
||
MOVE BUFROW(A6),A3
|
||
MOVEM.L SRCROW(A6),A2/A4-A5 ;srcRow, srcAddr (src bitmap), bufStart (dst bitmap)
|
||
maskBlt
|
||
;
|
||
; Get char height into D7
|
||
;
|
||
MOVE.W #255,D7 ;GET -1 BYTE, CLEAR HI BYTE
|
||
ADD.B TOPHT+1(A6),D7 ;CALC HEIGHT-1 FOR DBRA LOOP
|
||
BMI SKIPCH ;OOPS HEIGHT WAS ZERO !
|
||
;
|
||
; Adjust srcPtr and dstPtr for charTop
|
||
;
|
||
MOVEQ #0,D0 ;get ready for byte
|
||
MOVE.B TOPHT(A6),D0 ;get char top
|
||
MOVE.L A2,D4 ;get srcRow in D-reg
|
||
MULU.L D0,D4 ;calc charTop * srcRow
|
||
ADD.L D4,A4 ;add to srcPtr
|
||
MOVE A3,D4 ;get dstRow in D-reg
|
||
MULU D0,D4 ;calc charTop * dstRow
|
||
ADD.L D4,A5 ;add to dstPtr
|
||
;
|
||
; figure alignment offset in source so that dest is long aligned
|
||
;
|
||
MOVEQ #$1F,D0 ;get a 5 bit mask, needed later
|
||
MOVE.L D1,D5
|
||
;
|
||
; Setup dstPtr in A5, address of leftmost dst word
|
||
;
|
||
MOVE D3,D6 ;GET A COPY OF DSTLEFT
|
||
ASR #5,D6 ;CONVERT FROM DOTS TO LONGS
|
||
MOVE D6,D4 ;copy dest left in longs for later
|
||
LSL #2,D6 ;quad for bytes
|
||
ADD D6,A5 ;move dest pointer to top of character
|
||
|
||
;
|
||
; figure number of longs to move
|
||
;
|
||
MOVE D2,D6 ;copy dstRight
|
||
ASR #5,D6
|
||
SUB D4,D6 ;if same, it fits into a single long
|
||
BEQ fitsInLong ;most 1 bit deep characters fit into a long
|
||
|
||
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
||
;
|
||
; Character spans long in destination, so it must be moved in pieces
|
||
; Registers used at this point:
|
||
; D0 = 5 bit mask D1 = src offset D2 = dstRight D3 = dstLeft
|
||
; D4 = -- D5 = src offset D6 = longs to move D7 = character height
|
||
; A0 = -- A1 = character ptr A2 = source row sz A3 = dest row size
|
||
; A4 = source row ptr A5 = dest row ptr A6 = locals A7 = stack
|
||
|
||
NEG D3 ;negate for bit counting
|
||
AND D0,D3 ;get bottom 5 bits of dstLeft
|
||
BNE.S @skip32
|
||
MOVEQ #32,D3 ;if 0, make it 32
|
||
@skip32
|
||
|
||
MOVE D6,D4 ;total longs (not including left part)
|
||
LSL #2,D4 ;make it a byte count
|
||
SUB D4,A2 ;adjust source bump count
|
||
SUB D4,A3 ;adjust dest. bump count
|
||
SUBQ #1,D6 ;number of whole longs, less left & right parts
|
||
ADD D3,D1 ;the right hand start
|
||
MOVEQ #32,D4
|
||
SUB.L D4,D1
|
||
|
||
;
|
||
; if not 1 bit font & mode is not srcOr, do moves instead
|
||
;
|
||
TST.B orNotOK(A6)
|
||
BNE.S DoMove
|
||
|
||
;
|
||
; OR words to the screen; set up right mask
|
||
;
|
||
AND D0,D2 ;get bottom 5 bits of dstRight
|
||
MOVEQ #1,D4
|
||
ROR.L #1,D4 ;set the high bit
|
||
ASR.L D2,D4 ;$80000000 to $FFFFFFFF
|
||
ASL.L #1,D4 ;$00000000 to $FFFFFFFE
|
||
|
||
MOVE D6,D2 ;initialize whole long count
|
||
MOVE D6,A0 ;save long count for later
|
||
MOVE.L D5,D6
|
||
ADD D3,D6
|
||
MOVEQ #32,D0
|
||
SUB.L D0,D6
|
||
;
|
||
; Slow loop only taken in wierd cases where dst wider than a long.
|
||
; Or the more common case that the font is more than 1 bit deep
|
||
;
|
||
|
||
MAIN1
|
||
BFEXTU (A4){D5:D3},D0 ;GET SRC FROM BITMAP
|
||
BRA.S @checkLong ;see if there is some number of longs to do
|
||
@main2
|
||
BFEXTU (A4){D6:0},D0 ;GET SRC FROM BITMAP
|
||
@checkLong
|
||
OR.L D0,(A5)+ ;OR SRC INTO DST
|
||
ADDQ #4,A4 ;BUMP SRCPTR RIGHT
|
||
DBRA D2,@main2 ;LOOP TILL LAST long
|
||
|
||
BFEXTU (A4){D1:0},D0 ;GET SRC FROM BITMAP
|
||
AND.L D4,D0
|
||
OR.L D0,(A5) ;OR SRC INTO DST
|
||
ADD.L A2,A4 ;BUMP TO NEXT ROW
|
||
ADD.L A3,A5 ;BUMP DST TO NEXT ROW
|
||
WIDE1 MOVE A0,D2 ;GET long count
|
||
DBRA D7,MAIN1 ;LOOP ALL ROWS
|
||
BRA decCount ;skip mask blt part
|
||
|
||
;
|
||
; Handle case of drawing into the offscreen bit map in color separately
|
||
;
|
||
DoMove
|
||
MOVE D2,D4 ;copy dstRight
|
||
AND D0,D4 ;get bottom 5 bits of dstRight
|
||
|
||
MOVE D6,longCount(A6) ;save # of whole longs
|
||
MOVE D6,D2 ;set up first loop count
|
||
MOVE.L bkCol(A6),D6 ;get a long full of the background color
|
||
BFEXTU D6{0:D3},D0 ;background color & left mask
|
||
MOVE.L D0,leftBack(A6) ;save for quick compare
|
||
BFEXTU D6{0:D4},D0 ;background color & right mask
|
||
MOVE.L D0,rightBack(A6) ;right mask color compare
|
||
MOVE bitDepth(A6),D0 ;bits in a single pixel
|
||
BFEXTU D6{0:D0},D0 ;get a single pixel of the background color
|
||
MOVE D0,bkCol1(A6) ;a single background color for quick compare
|
||
MOVEQ #32,D6 ;
|
||
SUB D3,D6 ;
|
||
MOVE.L D5,A0
|
||
ADD D3,A0
|
||
SUB #32,A0 ;set up center move offset
|
||
|
||
;
|
||
; Slow loop taken in cases where dst wider than a long (common for fonts more than 1 bit
|
||
; deep.) Need to move only the pixels that are not colored same as background.
|
||
;
|
||
MoveLeft
|
||
BFEXTU (A5){D6:D3},D0 ;get current background of destination
|
||
CMP.L leftBack(A6),D0 ;compare it against the background color AND leftMask
|
||
BNE.S leftOnePix ;if different, must move 1 pixel at a time
|
||
;
|
||
; Here the destination has only background color pixels, so the whole thing can be moved
|
||
;
|
||
BFEXTU (A4){D5:D3},D0 ;GET SRC FROM BITMAP
|
||
BFINS D0,(A5){D6:D3}
|
||
checkLong
|
||
EXG A0,D5 ;set up center move offset
|
||
midChkLong
|
||
ADDQ #4,A5 ;bump destination
|
||
BRA.S checkMLong ;see if there is some number of longs to do
|
||
|
||
MoveMid
|
||
MOVE.L bkCol(A6),D0
|
||
CMP.L (A5),D0 ;same as background color?
|
||
BNE.S midOnePix ;if different, move 1 at a time
|
||
BFEXTU (A4){D5:0},D0 ;GET SRC FROM BITMAP
|
||
MOVE.L D0,(A5)+ ;OR SRC INTO DST
|
||
checkMLong
|
||
ADDQ #4,A4 ;BUMP SRCPTR RIGHT
|
||
DBRA D2,MoveMid ;LOOP TILL LAST WORD
|
||
|
||
MoveRight
|
||
EXG A0,D5 ;set up left move offset
|
||
TST D4
|
||
BEQ.S nextRow
|
||
BFEXTU (A5){0:D4},D0 ;look at the destination
|
||
CMP.L rightBack(A6),D0 ;compare it against the background AND rightMask
|
||
BNE.S rightOnePix ;if different, must move 1 pixel at a time
|
||
;
|
||
; Here the destination has only background color pixels, so the whole thing can be moved
|
||
;
|
||
BFEXTU (A4){D1:D4},D0 ;get the right part of the character
|
||
BFINS D0,(A5){0:D4} ;move it to the destination
|
||
nextRow
|
||
ADD.L A2,A4 ;BUMP TO NEXT ROW
|
||
ADD.L A3,A5 ;BUMP DST TO NEXT ROW
|
||
offMove
|
||
MOVE longCount(A6),D2 ;GET long count
|
||
DBRA D7,MoveLeft ;LOOP ALL ROWS
|
||
BRA checkMask
|
||
|
||
;
|
||
; need to move only the pixels that are not colored same as background
|
||
;
|
||
|
||
leftOnePix
|
||
MOVEM.L D1/D3-D6,-(SP) ;save temporary registers
|
||
MOVEM bkCol1(A6),D0/D1 ;D0 = back color D1 = pixel width
|
||
@nxtPixel
|
||
BFEXTU (A4){D5:D1},D4 ;pick up a source pixel
|
||
CMP D4,D0 ;is it the same as the back color?
|
||
BEQ.S @skipInsert ;if so, donÕt add to destination
|
||
BFINS D4,(A5){D6:D1} ;if not, copy it to the destination
|
||
@skipInsert
|
||
ADD.L D1,D5 ;move to next source pixel
|
||
ADD D1,D6 ;move to next destination pixel
|
||
SUB D1,D3 ;decrement count
|
||
BGT.S @nxtPixel ;do until weÕre done
|
||
MOVEM.L (SP)+,D1/D3-D6 ;restore bkCol, left & right widths, src & dest offsets
|
||
BRA.S checkLong
|
||
|
||
midOnePix
|
||
MOVEQ #32,D0 ;full long size in bits
|
||
MOVEM.L D1/D3-D6,-(SP) ;save temporary registers
|
||
MOVEQ #0,D6
|
||
MOVEM bkCol1(A6),D1/D3 ;D1 = back color D3 = pixel width
|
||
@nxtPixel
|
||
BFEXTU (A4){D5:D3},D4 ;pick up a source pixel
|
||
CMP D4,D1 ;is it the same as the back color?
|
||
BEQ.S @skipInsert ;if so, donÕt add to destination
|
||
BFINS D4,(A5){D6:D3} ;if not, copy it to the destination
|
||
@skipInsert
|
||
ADD.L D3,D5 ;move to next source pixel
|
||
ADD D3,D6 ;move to next destination pixel
|
||
SUB D3,D0 ;decrement count
|
||
BGT.S @nxtPixel ;do until weÕre done
|
||
MOVEM.L (SP)+,D1/D3-D6 ;restore bkCol, left & right widths, src & dest offsets
|
||
BRA midChkLong
|
||
|
||
rightOnePix
|
||
MOVEM.L D1/D3-D6,-(SP) ;save temporary registers
|
||
MOVEQ #0,D6
|
||
MOVEM bkCol1(A6),D3/D5 ;D3 = back color D5 = pixel width
|
||
@nxtPixel
|
||
BFEXTU (A4){D1:D5},D0 ;pick up a source pixel
|
||
CMP D0,D3 ;is it the same as the back color?
|
||
BEQ.S @skipInsert ;if so, donÕt add to destination
|
||
BFINS D0,(A5){D6:D5} ;if not, copy it to the destination
|
||
@skipInsert
|
||
ADD.L D5,D1 ;move to next source pixel
|
||
ADD D5,D6 ;move to next destination pixel
|
||
SUB D5,D4 ;decrement count
|
||
BGT.S @nxtPixel ;do until weÕre done
|
||
MOVEM.L (SP)+,D1/D3-D6 ;restore bkCol, left & right widths, src & dest offsets
|
||
BRA nextRow
|
||
|
||
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
||
; Here, the character does not cross a long boundary, so faster loops are in order.
|
||
;
|
||
|
||
fitsInLong
|
||
MOVE charWidth(A6),D3 ;set up character width in bits
|
||
TST.B notMaskPass(A6) ;if dest is 1 bit, or this is the mask,
|
||
BEQ.S @skipMul ;then skip the mul scale
|
||
MOVE bitShift(A6),D4 ;set up bit depth
|
||
LSL D4,D3
|
||
@skipMul
|
||
TST.B orNotOK(A6) ;can we OR?
|
||
BNE.S offLong ;if not, bit extract/insert instead
|
||
;
|
||
; Optimize if dst fits in one long. (most 1 bit deep characters do)
|
||
;
|
||
LONG1
|
||
;
|
||
; OR words to the screen; set up right mask
|
||
|
||
MOVE D2,D1 ;copy dest right
|
||
NEG D1 ;figure not bits from left but bits from right
|
||
AND D0,D1 ;but only from 0 to 31
|
||
ADD D1,D3 ;add right mask to extract width
|
||
|
||
AND D0,D2 ;get bottom 5 bits of dstRight
|
||
MOVEQ #1,D4
|
||
ROR.L #1,D4 ;set the high bit
|
||
ASR.L D2,D4 ;$80000000 to $FFFFFFFF
|
||
ASL.L #1,D4 ;$00000000 to $FFFFFFFE
|
||
|
||
; if D5 + D3 < 32, use a faster set of code:
|
||
|
||
longLoop
|
||
BFEXTU (A4){D5:D3},D0 ;GET SRC DATA
|
||
AND.L D4,D0
|
||
OR.L D0,(A5) ;OR RESULT INTO DST
|
||
ADD.L A2,A4 ;BUMP SRCPTR TO NEXT ROW
|
||
ADD.L A3,A5 ;BUMP DSTPTR TO NEXT ROW
|
||
DBRA D7,longLoop ;LOOP ALL ROWS
|
||
BRA.S decCount
|
||
;
|
||
; Optimize if dst fits in one long. (most normal characters do)
|
||
;
|
||
offLong
|
||
MOVE D2,D6
|
||
AND.L D0,D6
|
||
SUB D3,D6
|
||
BFEXTU bkCol(A6){0:D3},D2
|
||
MOVEM.L D5/D6,leftOffset(A6) ;save source left, destination left offsets
|
||
MOVE D5,D0 ;source left offset less
|
||
ADD D3,D0 ; width of pixels to be moved
|
||
MOVE D0,longCount(A6) ; determines inner loop bounds
|
||
MOVE bitDepth(A6),D4 ;get source depth
|
||
BFEXTU D2{0:D4},D1 ;set up 1 pixel of background color
|
||
|
||
offLongLoop
|
||
|
||
; check to see if existing destination is untouched (equal to background) so that there is no
|
||
; concern about obliterating over a part of a character that kerns into this space.
|
||
|
||
BFEXTU (A5){D6:D3},D0 ;get the existing background
|
||
CMP.L D2,D0 ;is it background colored?
|
||
BEQ.S @okToBlast ;if so, it is safe to cut and fill
|
||
|
||
; inner loop taken if some kerning has occured so that bits can not be moved directly over bkground
|
||
|
||
@nxtPixel
|
||
BFEXTU (A4){D5:D4},D0
|
||
CMP D0,D1
|
||
BEQ.S @skipInsert
|
||
BFINS D0,(A5){D6:D4}
|
||
@skipInsert
|
||
ADD D4,D6
|
||
ADD D4,D5
|
||
CMP longCount(A6),D5 ;where to stop with the mask
|
||
BLT.S @nxtPixel
|
||
MOVEM.L leftOffset(A6),D5/D6 ;restore source left, destination left offsets
|
||
BRA.S @nextRow
|
||
|
||
; if no kerning, data can be moved without concern for what is already there.
|
||
|
||
@okToBlast
|
||
BFEXTU (A4){D5:D3},D0 ;GET SRC DATA
|
||
BFINS D0,(A5){D6:D3} ;move to destination
|
||
@nextRow
|
||
ADD.L A2,A4 ;BUMP SRCPTR TO NEXT ROW
|
||
ADD.L A3,A5 ;BUMP DSTPTR TO NEXT ROW
|
||
DBRA D7,offLongLoop ;LOOP ALL ROWS
|
||
|
||
;
|
||
; here, set up things for mask blt
|
||
;
|
||
checkMask
|
||
TST bitShift(A6) ;is source depth 1?
|
||
BEQ.S decCount ;if so, skip mask (just copy result to mask later)
|
||
TST.B maskFont(A6)
|
||
BEQ.S decCount
|
||
SF orNotOK(A6) ;next time through, can OR the mask
|
||
SF notMaskPass(A6) ;force bitDepth to 1 this pass
|
||
MOVEM maskBlts(A6),D1-D3/A3 ;set up words
|
||
MOVEM.L mSrcROW(A6),A2/A4/A5 ;set up longs
|
||
BRA maskBlt ;then blt mask
|
||
|
||
decCount
|
||
SUB #1,charsRemain(A6) ;decrement total character count
|
||
SUB #1,countCopy(A6) ;decrement partial draw character count
|
||
BGT NEXTCH ;LOOP IF MORE CHARS LEFT
|
||
|
||
;------
|
||
|
||
STRDONE MOVE.L SAVEA5(A6),A5 ;RESTORE GLOBAL PTR
|
||
TST.B FASTFLAG(A6) ;WERE WE GOING DIRECT TO SCREEN ?
|
||
BEQ.S @1 ;NO, CONTINUE
|
||
TST.B CRSRFLAG(A6) ;DRAWING TO SCREEN?
|
||
BEQ.S @0 ;=>IF NOT, JUST RETURN
|
||
move.b MMUsave(a6),d0 ;get previous MMU state in d0
|
||
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
|
||
@32bitNot
|
||
_SHOWCURSOR ;YES, RESTORE CURSOR
|
||
@0 BRA GOHOME ;AND QUIT
|
||
@1 MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
|
||
MOVE.L THEPORT(A0),A3 ;GET CURRENT GRAFPORT
|
||
MOVE.L FONTPTR(A0),A4 ;POINT TO FMOUTPUT
|
||
MOVE.L 2(A4),A2 ;GET FONT HANDLE
|
||
MOVE.L (A2),A2 ;DE-REFERENCE IT
|
||
MOVE CHARLOC(A6),D7 ;GET FINAL CHARLOC INT PART
|
||
SUB fKernMax(A2),D7 ;UN-ADJUST FROM KERNING, but not italic
|
||
;
|
||
; Make buffer bold if necessary:
|
||
;
|
||
CKBOLD CLR D2 ;GET READY FOR BYTE
|
||
MOVE.B 6(A4),D2 ;GET NUMBER OF OVERSTRIKES
|
||
BRA.S NXTBOLD ;BOLD BUFFER IF ANY
|
||
BOLDIT MOVE.L BUFSTART(A6),A0 ;POINT TO START OF BUFFER
|
||
MOVE BUFSIZE(A6),D1 ;HOW MANY LONGS IN BUF
|
||
SUB D0,D0 ;CLEAR X-BIT
|
||
BOLDLP MOVE.L (A0),D0 ;GET ONE LONG
|
||
ROXR.L #1,D0 ;ROTATE RIGHT WITH EXTEND
|
||
OR.L D0,(A0)+ ;OR BACK INTO BUFFER
|
||
DBRA D1,BOLDLP ;LOOP ENTIRE BUFFER
|
||
NXTBOLD DBRA D2,BOLDIT ;LOOP FOR EACH OVERSTRIKE
|
||
|
||
|
||
;
|
||
; Slant the buffer if necessary:
|
||
; Work from bottom of buffer up, shifting each row right.
|
||
; Work right to left to avoid clobbering src.
|
||
;
|
||
MOVEQ #0,D2 ;GET READY FOR BYTE
|
||
MOVE.B 7(A4),D2 ;DO WE NEED ITALIC ?
|
||
BEQ.S CHECKUL ;NO, CONTINUE
|
||
|
||
MOVE.L BUFEND(A6),A1 ;DSTPTR:=END OF BUFFER
|
||
MOVE BUFROW(A6),D3 ;GET BUFFER ROWBYTES
|
||
SUB D3,A1 ;BACK UP DSTPTR TO END OF 2ND ROW
|
||
LSR #2,D3 ;LONGCNT:=ROWBYTES DIV 4
|
||
SUB #1,D3 ;LONGCOUNT-1 FOR DBRA LOOP
|
||
|
||
MOVE HEIGHT(A6),D6 ;INIT ROW COUNTER
|
||
MOVEQ #0,D4 ;INIT OFFSET
|
||
BRA.S DOSLANT ;GO TO LOOP START
|
||
NXTROW ADD.L D2,D4 ;OFFSET:=OFFSET+ITALIC
|
||
MOVE.L D4,D5 ;COPY OFFSET
|
||
LSR.L #4,D5 ;DELTA := OFFSET SCALED BY 16
|
||
NEG.L D5 ;make negative for BFEXTU
|
||
MOVE.L A1,A0 ;SRCPTR:=DSTPTR
|
||
SUB #4,A0 ;POINT TO LAST LONG
|
||
|
||
MOVE D3,D1 ;INIT LOOP TO LONGCNT
|
||
NXTLONG BFEXTU (A0){D5:0},D0 ;GET A SHIFTED LONG OF SRC
|
||
SUB #4,A0 ;BUMP SRCPTR LEFT ONE LONG
|
||
MOVE.L D0,-(A1) ;STORE IN DST AND BUMP DSTPTR
|
||
DBRA D1,NXTLONG ;LOOP ALL LONG THIS ROW
|
||
DOSLANT DBRA D6,NXTROW ;LOOP FOR ALL ROWS IN BUFFER
|
||
|
||
|
||
;
|
||
; Underline characters in buffer if necessary.
|
||
;
|
||
; Use characters in buffer to hide parts of the underline.
|
||
;
|
||
CHECKUL TST.B 10(A4) ;IS ULTHICK ZERO ?
|
||
BEQ.S NOTUL ;YES, CONTINUE
|
||
MOVE.L BUFSTART(A6),A0 ;POINT TO BUFFER START
|
||
MOVE BUFROW(A6),D1 ;GET BYTES PER ROW OF BUFFER
|
||
MOVE locASCENT(A2),D0 ;GET ASCENT
|
||
MOVE locDESCENT(A2),D2 ;GET DESCENT
|
||
MULU D1,D0
|
||
ADD.L D0,A0 ;POINT TO BASELINE ROW
|
||
MOVE.L A0,A1
|
||
MOVE.L A0,A2
|
||
ADD D1,A1 ;POINT TO BASELINE+1
|
||
CMP #2,D2 ;IS DESCENT AT LEAST 2 ?
|
||
BLT.S NOTUL ;NO, SKIP UNDERLINE
|
||
BEQ.S ONLY2 ;ONLY USE 2 IF DESCENT=2
|
||
ADD D1,A2
|
||
ADD D1,A2 ;POINT TO BASELINE+2
|
||
ONLY2 SUB D1,SP ;ALLOCATE TEMP SCANBUF
|
||
MOVE.L A3,-(SP) ;SAVE GRAFPORT
|
||
LEA 4(SP),A3 ;POINT TO START OF TEMP
|
||
LSR #2,D1 ;CONVERT BYTES TO LONGS
|
||
SUB #1,D1 ;INIT DBRA LOOP COUNT
|
||
MOVE D1,D2 ;COPY LOOP COUNT
|
||
SUB D0,D0 ;CLEAR X-BIT
|
||
UL1 MOVE.L (A0)+,D0 ;GET FROM BASELINE
|
||
OR.L (A1)+,D0 ;OR WITH BASELINE+1
|
||
OR.L (A2)+,D0 ;OR WITH BASELINE+2
|
||
MOVE.L D0,(A3) ;PUT RESULT TO TEMP
|
||
ROXR.L #1,D0 ;SHIFT WITH CARRY
|
||
OR.L D0,(A3)+ ;OR INTO TEMP
|
||
DBRA D1,UL1 ;LOOP ALL LONGS IN ROW
|
||
|
||
MOVE.L A1,A0 ;COPY END PTR
|
||
SUB D0,D0 ;CLEAR X-BIT
|
||
UL2 MOVE.L -(A3),D0 ;GET FROM TEMP
|
||
ROXL.L #1,D0 ;SHIFT LEFT WITH CARRY
|
||
OR.L (A3),D0 ;OR WITH TEMP
|
||
NOT.L D0 ;INVERT
|
||
OR.L D0,-(A1) ;DRAW SOME UNDERLINE
|
||
DBRA D2,UL2 ;LOOP ALL LONGS IN ROW
|
||
MOVE.L (SP)+,A3 ;RESTORE GRAFPORT
|
||
;
|
||
; Setup fakeRgn, a dummy rectangular region
|
||
;
|
||
NOTUL MOVE #10,FAKERGN+RGNSIZE(A6) ;SIZE=10 BYTES FOR RECT RGN
|
||
MOVE.L DSTPIX+BOUNDS(A6),FAKERGN+RGNBBOX(A6)
|
||
MOVE.L DSTPIX+BOUNDS+4(A6),FAKERGN+RGNBBOX+4(A6)
|
||
LEA FAKERGN(A6),A0 ;GET ADDR OF FAKERGN
|
||
MOVE.L A0,FAKEPTR(A6) ;POINT FAKE MASTERPTR TO IT
|
||
|
||
|
||
;
|
||
; SET UP SOURCE BITMAP TO TRANSFER TO SCREEN
|
||
;
|
||
; SRCPIX := buffer
|
||
;
|
||
|
||
LEA SRCBITS(A6),A0 ;POINT TO source bits
|
||
MOVE.L A0,A1
|
||
MOVE.L BUFSTART(A6),(A0)+ ;SET UP BASEADDR
|
||
MOVE BUFROW(A6),(A0)+ ;SET UP ROWBYTES
|
||
MOVE TEXTRECT+TOP(A6),(A0)+ ;SET UP BOUNDS TOP
|
||
MOVE BUFLEFT(A6),(A0)+ ;SET UP BOUNDS LEFT
|
||
MOVE.L TEXTRECT+BOTRIGHT(A6),(A0)+ ;SET UP BOTTOM RIGHT
|
||
LEA SRCPIX(A6),A2
|
||
_BitsToPix
|
||
TST.B maskFont(A6)
|
||
BEQ.S @finishSrcPix
|
||
LEA maskBits(A6),A0 ;POINT TO mask bits
|
||
MOVE.L maskStart(A6),(A0)+ ;SET UP BASEADDR
|
||
MOVE mBufRow(A6),(A0)+ ;SET UP ROWBYTES
|
||
MOVE TEXTRECT+TOP(A6),(A0)+ ;SET UP BOUNDS TOP
|
||
MOVE BUFLEFT(A6),(A0)+ ;SET UP BOUNDS LEFT
|
||
MOVE.L TEXTRECT+BOTRIGHT(A6),(A0)+ ;SET UP BOTTOM RIGHT
|
||
@finishSrcPix
|
||
TST bitShift(A6) ;is the bit depth 1?
|
||
BEQ.S @skipColorJam
|
||
MOVE bitDepth(A6),srcPix+pixelSize(A6) ;set up bit depth
|
||
MOVE.L dstPix+pmTable(A6),srcPix+pmTable(A6) ;set up color table
|
||
@skipColorJam
|
||
|
||
;
|
||
; check if any shadowing:
|
||
;
|
||
CLR D3 ;GET READY FOR BYTE
|
||
MOVE.B 11(A4),D3 ;GET SHADOW COUNT
|
||
BEQ NOSHAD ;SKIP IF NO SHADOWING
|
||
|
||
;
|
||
; Shadowing will be used. Allocate buf2, 4 scans taller than BUF1.
|
||
; Clear out new 4 scanlines, and copy BUF1 into the rest.
|
||
;
|
||
MOVE BUFROW(A6),D0 ;GET 4 * NUMBER OF LONGS PER ROW
|
||
SUB #1,D0 ;INIT LOOP COUNTER
|
||
CLR.L -(SP) ;ALLOW ONE LONG OF SLOP
|
||
MOVE.L SP,BUF2END(A6) ;REMEMBER END OF BUF2
|
||
CLR2 CLR.L -(SP) ;ALLOCATE AND CLEAR A LONG
|
||
DBRA D0,CLR2 ;CLEAR 4 SCANLINES WORTH
|
||
MOVE BUFSIZE(A6),D0 ;GET NUMBER OF LONGS IN BUF1
|
||
SUB #1,D0 ;INIT DBRA COUNTER
|
||
MOVE.L BUFEND(A6),A0 ;POINT TO END OF BUF1
|
||
COPYLP MOVE.L -(A0),-(SP) ;COPY FROM BUF1 TO NEW BUF2
|
||
DBRA D0,COPYLP ;COPY ALL OF BUF1
|
||
MOVE.L SP,BUF2START(A6) ;REMEMBER START OF BUF2
|
||
CLR.L -(SP) ;ALLOW ONE LONG OF SLOP
|
||
|
||
;
|
||
; Bold buf2 across to the right enough for shadow.
|
||
;
|
||
AND #3,D3 ;RESTRICT SHADOW COUNT TO 1..3
|
||
MOVE D3,D2 ;INIT BOLD COUNTER
|
||
ACROSS1 MOVE.L BUF2START(A6),A0 ;POINT TO START OF BUFFER2
|
||
MOVE BUFSIZE(A6),D1 ;INIT COUNT OF LONGS
|
||
SUB D0,D0 ;CLEAR X-BIT
|
||
ACROSS2 MOVE.L (A0),D0 ;GET A LONG FROM BUF2
|
||
ROXR.L #1,D0 ;SHIFT IT RIGHT EXTENDED
|
||
OR.L D0,(A0)+ ;OR IT BACK INTO BUFFER
|
||
DBRA D1,ACROSS2 ;LOOP FOR ALL LONGS
|
||
DBRA D2,ACROSS1 ;BOLD RIGHT 2,3, OR 4 TIMES
|
||
|
||
;
|
||
; Bold BUF2 down enough for shadow.
|
||
;
|
||
MOVE.L BUF2START(A6),A2 ;GET LIMIT POINTER
|
||
DOWN1 MOVE.L BUF2END(A6),A1 ;DSTPTR:=END OF BUF2
|
||
MOVE.L A1,A0
|
||
MOVE SRCBITS+ROWBYTES(A6),D2 ;GET SRC ROWBYTES
|
||
SUB D2,A0 ;SRCPTR:=END - 1 SCANLINE
|
||
DOWN2 MOVE.L -(A0),D0 ;GET A LONG FROM LINE ABOVE
|
||
OR.L D0,-(A1) ;OR INTO THIS LINE
|
||
CMP.L A2,A0 ;IS SRCPTR <= BUF2START ?
|
||
BGT.S DOWN2 ;NO, LOOP ALL LONGS
|
||
DBRA D3,DOWN1 ;BOLD DOWN 2,3, OR 4 TIMES
|
||
|
||
; XOR the plain text into the shadow buffer
|
||
|
||
MOVE bufSize(A6),D1 ;size of buffers in longs
|
||
MOVE.L bufStart(A6),A0 ;start of plain text
|
||
MOVE.L A2,A1 ;start of shadowed text
|
||
ADD D2,A1 ;bump down a line in the shadowed text
|
||
SUB D0,D0 ;clear x bit
|
||
@xor
|
||
MOVE.L (A0)+,D0 ;a line of plain text
|
||
ROXR.L #1,D0 ;shift it right, extended
|
||
EOR.L D0,(A1)+ ;combine with shadowed text
|
||
DBRA D1,@xor ;repeat for all longs
|
||
|
||
;
|
||
; Alter SRCBITS to use BUF2
|
||
;
|
||
MOVE.L A2,SRCBITS+BASEADDR(A6) ;SRC BASEADDR:=BUF2START
|
||
ADD #4,SRCBITS+BOUNDS+BOTTOM(A6) ;4 SCANS TALLER
|
||
;
|
||
; Push params and call StretchBits to transfer shadow to screen
|
||
;
|
||
MOVE.L TEXTRECT(A6),SRCRECT(A6) ;DSTRECT := SRCRECT
|
||
MOVE.L TEXTRECT+4(A6),SRCRECT+4(A6)
|
||
ADD #4,SRCRECT+BOTTOM(A6) ;PLUS 4 SCANS TALLER
|
||
MOVE.L SRCRECT(A6),DSTRECT(A6)
|
||
MOVE.L SRCRECT+4(A6),DSTRECT+4(A6)
|
||
LEA DSTRECT+TOP(A6),A0 ;OFFSET BY (-1,-1)
|
||
SUB #1,(A0)+ ;TOP
|
||
SUB #1,(A0)+ ;LEFT
|
||
SUB #1,(A0)+ ;BOTTOM
|
||
SUB #1,(A0)+ ;RIGHT
|
||
|
||
TST.B STRETCH(A6)
|
||
BEQ.S @1
|
||
PEA DSTRECT(A6)
|
||
PEA FROMRECT(A6)
|
||
PEA TORECT(A6)
|
||
_MAPRECT ;THEN MAPPED FOR SCALING
|
||
@1
|
||
|
||
PEA SRCBITS(A6) ;PUSH SRCPIX
|
||
MOVE.L maskBitsPtr(A6),-(SP) ;a mask?
|
||
BEQ.S @noMask
|
||
MOVE.L 4(SP),(SP) ;replace mask with copy of source
|
||
@noMask
|
||
PEA PORTBITS(A3) ;TRANSFER TO SCREEN
|
||
PEA SRCRECT(A6) ;PUSH SRCRECT = TEXTRECT
|
||
PEA SRCRECT(A6) ;maskRect same as source rect
|
||
PEA DSTRECT(A6) ;PUSH DSTRECT = TEXTR2
|
||
MOVE locMode(A6),-(SP) ;PUSH TEXTMODE
|
||
CLR.L -(SP) ;NO PATTERN FOR NOW
|
||
MOVE.L CLIPRGN(A3),-(SP) ;PUSH CLIPRGN HANDLE
|
||
MOVE.L VISRGN(A3),-(SP) ;PUSH VISRGN HANDLE
|
||
PEA FAKEPTR(A6) ;PUSH FAKE HANDLE
|
||
CLR -(SP) ;pass multicolor flag false
|
||
_StretchBits ;TRANSFER BUFFER TO SCREEN
|
||
|
||
; if old port, srcOr, draw center part in bic; if bic, in srcOr
|
||
; (This is done for compatibility with older applications like MacProject and MacDraw that
|
||
; expect to put text on an arbitrary background, relying on the center of the shadow to show.)
|
||
|
||
TST portBits+rowBytes(A3) ;a new port?
|
||
BMI.S GOHOME
|
||
MOVE locMode(A6),D0
|
||
CMP #srcOr,D0
|
||
BEQ.S @useBic
|
||
CMP #srcBic,D0
|
||
BNE.S GOHOME
|
||
@useBic
|
||
|
||
; restored altered srcBits
|
||
|
||
MOVE.L bufStart(A6),srcBits+baseAddr(A6)
|
||
SUB #4,srcBits+bounds+bottom(A6)
|
||
|
||
; adjust params for center portion StretchBits
|
||
|
||
CLR.L maskBitsPtr(A6) ;no mask
|
||
EOR #2,D0 ;change or to bic, bic to or
|
||
MOVE D0,locMode(A6) ;adjust textmode
|
||
|
||
;
|
||
; Push params and call StretchBits to transfer buffer to screen
|
||
;
|
||
NOSHAD
|
||
PEA SRCPIX(A6) ;PUSH SRCBITS
|
||
MOVE.L maskBitsPtr(A6),-(SP) ;may be 0 if no mask bitmap
|
||
PEA PORTBITS(A3) ;TRANSFER TO SCREEN
|
||
PEA TEXTRECT(A6) ;PUSH SRCRECT = TEXTRECT
|
||
PEA TEXTRECT(A6) ;maskRect same as source rect
|
||
PEA TEXTR2(A6) ;PUSH DSTRECT = TEXTR2
|
||
MOVE locMode(A6),-(SP) ;PUSH TEXTMODE
|
||
CLR.L -(SP) ;NO PATTERN FOR NOW
|
||
MOVE.L CLIPRGN(A3),-(SP) ;PUSH CLIPRGN HANDLE
|
||
MOVE.L VISRGN(A3),-(SP) ;PUSH VISRGN HANDLE
|
||
PEA FAKEPTR(A6) ;PUSH FAKE HANDLE
|
||
MOVE.B colorSource(A6),-(SP) ;pass multicolor flag true if source is multibit
|
||
_StretchBits ;TRANSFER BUFFER TO SCREEN
|
||
|
||
GOHOME
|
||
MOVE.L saveStk(A6),SP ;throw away the buffers
|
||
MOVE charsRemain(A6),D0
|
||
SUB countCopy(A6),D0
|
||
MOVE D0,charsRemain(A6) ;if iterative, this will be greater than zero
|
||
BGT secondHalf ;so there are more characters to draw
|
||
BSET #hiliteBit,HiliteMode ;reset hilite override, in case colormap was skipped
|
||
TST stackOffset(A6) ;was the stack aligned?
|
||
MOVEM.L (SP)+,D0-D7/A1-A4 ;RESTORE REGS
|
||
UNLK A6
|
||
BEQ.S @skipAlign
|
||
ADDQ #2,SP
|
||
@skipAlign
|
||
RTD #PARAMSIZE ;Return and pop the stack <1.6-11april89-CEL>
|
||
|
||
ENDPROC
|
||
;
|
||
; < ABOVE COPIED VERBATIM FROM THE ROM >
|
||
;
|
||
;---------------------------------------------------------------------------------------
|
||
ENDIF ; <6.0.5> <CEL>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
;____________________________________________________________________________ dba <3.0>
|
||
; Menu manager patch
|
||
;
|
||
; The following patch fixes the head of InitProcMenu. The wrong version was
|
||
; rolled into the ROM, so we replace the head with this.
|
||
|
||
NewInitProcMenu proc export
|
||
|
||
ROMIMCommon equ $16D52 ; place to rejoin ROM in InitMenus
|
||
|
||
; the following code is copied out of the Menu Manager
|
||
|
||
move.l (sp)+,a0 ; get the return address
|
||
move.w (sp)+,d1 ; get the MBDF resource ID
|
||
move.l a0,-(sp) ; put return address back on the stack
|
||
jsrROM ROMIMCommon ; call InitMenus <4.0>
|
||
move.l MenuList,a0 ; get the menu list <4.0>
|
||
move.l (a0),a0 ; dereference the menu list <4.0>
|
||
move.w d1,mbResID(a0) ; store MBDF ID <4.0>
|
||
rts ; return to InitProcMenu caller <4.0>
|
||
|
||
endproc
|
||
|
||
; The following patch reinstates the WaitMouseUp in MenuSelect. It was removed as part
|
||
; of the tear-off menu stuff (in an attempt to support double-clicking in the menu bar),
|
||
; but that change was probably not a good idea, even for the tear-off menu case.
|
||
|
||
NewMenuSelect proc export
|
||
|
||
ROMContinueMenuSelect equ $171A2 ; place to rejoin ROM in MenuSelect
|
||
ROMDoneMenuSelect equ $17296 ; place to rejoin ROM in MenuSelect
|
||
|
||
; the following code is copied out of the Menu Manager
|
||
|
||
;-----------------------------------------------
|
||
; MenuSelect stack frame definitions
|
||
;-----------------------------------------------
|
||
|
||
STARTPT EQU 8 ; 1st parameter is 8, and is 4 bytes long
|
||
FUNCRESULT EQU 12 ; longword function result (menu,item)
|
||
ITEMRESULT EQU 14 ; item portion of funcResult
|
||
|
||
MENURECT EQU -8 ; rectangle (8 bytes)
|
||
MSavePort EQU MENURECT-4 ; saved grafPort
|
||
|
||
msLastMenu EQU MSavePort-2 ; how many menus are on the screen
|
||
DelayTicks EQU msLastMenu - 4 ; how long mouse in HItem
|
||
DragTicks EQU DelayTicks - 4 ; how long mouse moving towards HMenu
|
||
menuDelaySave EQU DragTicks - 1 ; store menuDelay from pRAM
|
||
menuDragSave EQU menuDelaySave - 1 ; store menuDrag from pRAM
|
||
lastFuncResult EQU menuDragSave - 2 ; funcResult last time thru MSLoop
|
||
lastItemResult EQU lastFuncResult - 2 ; itemResult last time thru MSLoop
|
||
firstMenuID EQU lastItemResult - 2 ; ID of REGULAR menu up
|
||
NewHMenuOffset EQU firstMenuID - 2 ; offset into MenuList of new HMenu
|
||
tRect1 EQU NewHMenuOffset - 8 ; temp rectangle
|
||
SelectFrame EQU tRect1 ; number of bytes to save
|
||
|
||
;-----------------------------------------------
|
||
|
||
link a6,#SelectFrame ; set up a stack frame
|
||
movem.l d2-d7/a2-a4,-(sp) ; save work registers
|
||
|
||
clr.w -(sp) ; push zero for this
|
||
_HiliteMenu ; make sure no menu is hilited
|
||
clr.l funcResult(a6) ; assume nothing will be selected
|
||
clr.l MenuDisable ; clear the low-memory location MenuDisable
|
||
|
||
clr.w -(sp) ; push zero for this
|
||
_WaitMouseUp ; is the mouse still down?
|
||
tst.b (sp)+ ; examine result
|
||
beq.s DoneMenuSelect ; if not still down, donÕt bother
|
||
jmpROM ROMContinueMenuSelect ; continue in ROM
|
||
DoneMenuSelect jmpROM ROMDoneMenuSelect ; continue in ROM
|
||
|
||
endproc
|
||
|
||
|
||
;____________________________________________________________________________ djw <3.6>
|
||
; Slot Manager pInitEntry patch
|
||
;
|
||
; Fixes a bug when calling _InsertSRTRec, inserting a ROM sRsrc with a valid
|
||
; refnum, pInitEntry is called. pInitEntry calls _sFindDevBase to calc a base
|
||
; addr to place in the DCE. The bug is _sFindDevBase is called with a bad
|
||
; sRsrc id. The fix is one line to restore the spId before calling
|
||
; _sFindDevBase.
|
||
;
|
||
|
||
pInitEntry Proc Export
|
||
With spBlock,srrBlock,SlotRsrcType
|
||
|
||
ROMpInitEntry Equ $00006904 ; addr to continue to in ROM
|
||
ROMpInitError Equ $0000691c ; addr of @Error label in ROM
|
||
ROMpInitDone Equ $00006920 ; addr of @Done label in ROM
|
||
ROMMapUnit Equ $00006930 ; addr of MapUnit routine in ROM
|
||
|
||
MOVEM.L D1/A2,-(SP) ; save regs
|
||
SUBA.W #SRSize,SP ; alloc size to read sRsrc sType field
|
||
MOVEA.L SP,A2 ; save A2 = ptr to buffer
|
||
|
||
; Fill in the fields of a new SRT entry
|
||
|
||
MOVE.B spSlot(A0),srrSlot(A1) ; slot number
|
||
MOVE.B spId(A0),srrId(A1) ; sRsrc id
|
||
MOVE.B spExtDev(A0),srrExtDev(A1) ; external device id
|
||
CLR.B srrHWDev(A1) ; clear hardware device id
|
||
MOVE.W spRefNum(A0),srrRefNum(A1) ; driver reference number
|
||
MOVE.W spIOReserved(A0),srrIOReserved(A1) ; IO reserved field (good for nothin?)
|
||
MOVE.L spsPointer(A0),srrsRsrcPtr(A1) ; set the ptr to the RAM or ROM sRsrc
|
||
CLR.L srrFlags(A1) ; clear flag field
|
||
MOVE.L spParamData(A0),D0 ; test state of enable/disable value
|
||
BEQ.S @ReadStuff ; zero - sRsrc is marked as enabled
|
||
BSET.B #srDisable,srrFlags+3(A1) ; set flag to indicate disabled
|
||
|
||
; Read the hardware sRsrc id
|
||
|
||
@ReadStuff MOVE.B #sRsrcHWDevId,spId(A0) ; get hardware id (if present)
|
||
_sReadByte ; no error if not present
|
||
BNE.S @Continue
|
||
MOVE.B spResult+3(A0),srrHWDev(A1) ; only a byte value
|
||
|
||
; Find and read the sRsrc type field <category><type><drvrSW><drveHW>
|
||
|
||
@Continue MOVE.B #sRsrcType,spId(A0) ; get ptr to sRsrc type
|
||
_sFindStruct
|
||
BNE.S @Error ; error - sRsrc type field is required
|
||
MOVE.L #SRSize,spSize(A0) ; set size to read
|
||
MOVE.L A2,spResult(A0) ; set buffer ptr
|
||
_sReadStruct
|
||
BNE.S @Error ; error - found but can't read ?
|
||
MOVE.L sCategory(A2),srrCategory(A1) ; copy <cat><type>
|
||
MOVE.L sDrvrSw(A2),srrDrvrSw(A1) ; copy <drvrSW><drvrHW>
|
||
|
||
; If there is a valid reference number, then find the DCE and calculate the dCtlDevBase
|
||
|
||
MOVEQ #0,D0 ; set a good return
|
||
MOVE.W spRefNum(A0),D1 ; get ref num
|
||
BEQ.S @Done ; no ref num - done
|
||
jsrROM ROMMapUnit ; return reg A2 = ptr to DCE
|
||
BNE.S @Error ; some error with ref num or DCE
|
||
|
||
; Read a 24 or 32 bit base address from the sResource
|
||
|
||
move.b srrId(a1),spId(a0) ; set spId of sRsrc to get base addr (the fix)
|
||
jmpROM ROMpInitEntry ; continue in ROM
|
||
|
||
; Jump points back into ROM
|
||
|
||
@Error jmpROM ROMpInitError ; jump to @Error label
|
||
@Done jmpROM ROMpInitDone ; jump to @Done label
|
||
|
||
EndProc
|
||
|
||
|
||
;____________________________________________________________________________ DAF <4.1>
|
||
; This patch really didn't get in until <5.1>
|
||
;
|
||
; SaveEntries Patch
|
||
;
|
||
; OK, I blew it on a patch roll-in from ROM78Fix into the Aurora ROM. In SaveEntries
|
||
; the a test was added for non-CLUT devices, but when I rolled it inline, I jumped
|
||
; back to the wrong place. This patch head patches the routine just like ROM78Fix
|
||
; so that it never hits the ROM routine if there is an error.
|
||
;
|
||
|
||
mySaveEntries PROC EXPORT
|
||
|
||
ROMSaveEntries EQU $3C920
|
||
|
||
MOVE.L ([theGDevice]),A0 ; get a pointer to the current device
|
||
CMP.W #CLUTType,GDType(A0) ; is it a clut device?
|
||
BNE.S SEDevErr ; nope, so report an error
|
||
JMPRom ROMSaveEntries ; OK, so execute normal saveEntries
|
||
SEDevErr
|
||
MOVE.W #cDevErr,QDErr ; post error code
|
||
RTD #12 ; and return
|
||
|
||
;____________________________________________________________________________
|
||
; SetEntries, dvb < 124 > 1991
|
||
; Mark bit 3 of QDSpare0 when the color environment changes, so pmgrexit
|
||
; only cleans up if bit was set for that layer.
|
||
|
||
mySetEntries PROC EXPORT
|
||
ROMSetEntries EQU $3C6C0
|
||
|
||
; Mark QDSpare that the color environment has changed, but only if
|
||
; QD exists
|
||
TST.B QDExist ; is QD around?
|
||
BNE.S @noQDE ; no, skip this next
|
||
MOVE.L (A5),A0
|
||
BSET #3,QDSpare0(A0) ; Tell PMgrExit to do color cleaning
|
||
@noQDE
|
||
JMPRom ROMSetEntries ; and on with our regularly scheduled program. < 124 >
|
||
|
||
;____________________________________________________________________________
|
||
; Script Manager patch to Pack6, fixes problem with pointer to unlocked
|
||
; handle in Transliterate. <4.3><08/21/89 pke>
|
||
; Also fixes another problem in LwrString, CharType, Transliterate, FindWord:
|
||
; These routines need to have the Script Manager IntlForce flag cleared
|
||
; before calling IUGetIntl (this flag must be saved beforehand and restored
|
||
; afterward). This ensures that the itl2 tables used by these routines apply
|
||
; to the current script. <4.5><08/21/89 pke>
|
||
; Only do the second fix for Scripts604 OR (SysVers > $604) <4.7><08/21/89 pke>
|
||
;
|
||
; This patch is not installed for A/UX, since A/UX doesn't support the Script
|
||
; Manager.
|
||
;
|
||
|
||
IF doScriptMgrPack6Fix AND (NOT installScriptMgrPtch39) THEN ; <42><50>
|
||
|
||
ptchPack6 PROC Export
|
||
|
||
fromROMLwrString EQU $0C0B2
|
||
fromROMCharType EQU $1D986
|
||
fromROMFindWord EQU $1DBE0
|
||
|
||
fromROMTranslit EQU $1DB34
|
||
toROMTranslit EQU $1DB3A
|
||
ROMPack6 EQU $262B2
|
||
|
||
tlRecord record {a6link},decr
|
||
result ds.w 1 ; function result.
|
||
tlArgs equ *-8 ; size of arguments.
|
||
srcHandle ds.l 1 ; srcHandle.
|
||
dstHandle ds.l 1 ; dstHandle.
|
||
target ds.w 1 ; target.
|
||
srcMask ds.l 1 ; srcMask.
|
||
selector ds.l 1 ; selector
|
||
return ds.l 1 ; return address.
|
||
a6link ds.l 1 ; old a6 register.
|
||
tlLocals equ * ; size of local variables.
|
||
endr
|
||
|
||
cmp.w #iuGetIntl,4(sp) ; is it an IUGetIntl call?
|
||
bne.s @NoPatch ; skip if not (optimization)
|
||
CmpRA fromROMLwrString,(sp)
|
||
beq.s @PatchOther
|
||
CmpRA fromROMCharType,(sp)
|
||
beq.s @PatchOther
|
||
CmpRA fromROMFindWord,(sp)
|
||
beq.s @PatchOther
|
||
CmpRA fromROMTranslit,(sp)
|
||
beq.s @PatchTrans ; Translit is special - 2 bugs
|
||
@NoPatch
|
||
JmpROM ROMPack6 ; nothing interesting to do
|
||
|
||
@PatchTrans
|
||
; We get here if we came from the _IUGetIntl in Transliterate (IUGetIntl is a
|
||
; macro that pushes a selector and then does a _Pack6 trap). A few instructions
|
||
; before the _IUgetIntl, we had handles in a1 and a2 which were then dereferenced
|
||
; into the same registers. We want to postpone this dereferencing till after
|
||
; _Pack6. Fortunately, the original handles are still available in Transliterate's
|
||
; a6 frame, so we can get them after the Pack6 call, dereference them again, and
|
||
; stuff them where they belong. We also need to clear the IntlForce flag around
|
||
; Pack6 if it is set.
|
||
|
||
WITH tlRecord, SMgrRecord
|
||
addq #4,sp ; kill old return address
|
||
|
||
GetSMgrCore a0 ; get pointer to SMgrRecord
|
||
tst.b smgrIntlForce(a0) ; check IntlForce flag
|
||
bne.s @fixFlag ; if set, go fix it
|
||
|
||
JsrROM ROMPack6
|
||
bra.s @doDeref
|
||
@fixFlag
|
||
clr.b smgrIntlForce(a0) ; now force it to 0
|
||
JsrROM ROMPack6
|
||
GetSMgrCore a0 ; get pointer to SMgrRecord
|
||
st smgrIntlForce(a0) ; restore IntlForce
|
||
@doDeref
|
||
; The next two lines are what follow the _IUGetIntl in the ROM Transliterate
|
||
move.l (sp)+,a4 ;
|
||
movem.l (sp)+,a1/d1-d2 ;
|
||
; Now we expect to have pointers in a1 and a2, so set them up again (this is
|
||
; the fix) and jump back into ROM:
|
||
move.l srcHandle(a6),a1 ; get source handle.
|
||
move.l dstHandle(a6),a2 ; get destination handle.
|
||
move.l (a1),a1 ; get source pointer.
|
||
move.l (a2),a2 ; get destination pointer.
|
||
JmpROM toROMTranslit
|
||
ENDWITH
|
||
|
||
@PatchOther
|
||
; We get here if we came from the _IUGetIntl in LwrString, CharType, or
|
||
; FindWord. If IntlForce is currently zero, we just JMP to the old Pack6.
|
||
; Otherwise, we copy part of the stack in order to save the return address,
|
||
; then JSR to Pack6, then fix up the stack.
|
||
|
||
WITH SMgrRecord
|
||
GetSMgrCore a0 ; get pointer to SMgrRecord
|
||
tst.b smgrIntlForce(a0) ; check IntlForce flag
|
||
beq.s @NoPatch ; if already 0, nothing to do
|
||
clr.b smgrIntlForce(a0) ; now force it to 0
|
||
|
||
; At this point the stack has 12 bytes that are significant for Pack6:
|
||
; 8(sp).L = space for returned handle
|
||
; 6(sp).W = argument, specifies which itlx
|
||
; 4(sp).W = Pack6 routine selector = #iuGetIntl
|
||
; 0(sp).L = return address
|
||
; We now copy the selector, argument, and return space below the return address.
|
||
; This sets up the stack correctly for the JsrROM (which will add a new return
|
||
; address) while preserving our original return address.
|
||
|
||
clr.l -(sp) ; new place for returned handle
|
||
move.l 8(sp),-(sp) ; copy selector and arguments
|
||
|
||
; Now this piece of stack has changed as follows:
|
||
; 16(sp).L = old space for returned handle
|
||
; 14(sp).W = old copy of argument (unnecessary)
|
||
; 12(sp).W = old copy of selector (unnecessary)
|
||
; 8(sp).L = old return address
|
||
; 4(sp).L = new space for returned handle
|
||
; 2(sp).W = new copy of argument, specifies which itlx
|
||
; 0(sp).W = new copy of Pack6 routine selector = #iuGetIntl
|
||
; We are now set up to call Pack6:
|
||
|
||
JsrROM ROMPack6
|
||
|
||
; The last stack picture:
|
||
; 12(sp).L = old space for returned handle
|
||
; 10(sp).W = nothing useful
|
||
; 8(sp).W = nothing useful
|
||
; 4(sp).L = old return address
|
||
; 0(sp).L = returned handle
|
||
; We need to copy the returned handle to where it should go, clean up the stack,
|
||
; set IntlForce, and return.
|
||
|
||
move.l (sp)+,8(sp) ; copy returned handle to its place
|
||
move.l (sp)+,a1 ; get return address
|
||
addq #4,sp ; finish cleaning up stack
|
||
GetSMgrCore a0 ; get pointer to SMgrRecord
|
||
st smgrIntlForce(a0) ; restore IntlForce
|
||
|
||
; Now we just have the returned handle on the stack (see, no picture).
|
||
|
||
jmp (a1) ; go home (I'm about to).
|
||
|
||
ENDWITH
|
||
ENDPROC
|
||
|
||
ENDIF ; <42>
|
||
|
||
;============================================================================ pke <4.6>
|
||
; Patch UprString,RelString,CmpString to reintroduce the bug in which "`" is
|
||
; converted to uppercase as "a". This is necessary to prevent HFS problems,
|
||
; since existing disk catalogs use the old, buggy sorting. All we need to do
|
||
; is patch them up to the point where they access the UpperTab table, which
|
||
; does not have the necessary bug in ROM.
|
||
;
|
||
; A/UX uses the ROM versions of these routines, so we can install them for
|
||
; A/UX.
|
||
;
|
||
PROC
|
||
EXPORT NewUprString,NewCmpString,NewRelString
|
||
|
||
ROMUprStringAfterEntString equ $0C10C
|
||
ROMRelStringAfterEntString equ $0C136
|
||
ROMEntStringAfterLEAUpperTab equ $0C196
|
||
|
||
;______________________________________________________________________
|
||
;
|
||
; Routine: UprString
|
||
; Arguments: D0.W (input) -- string length
|
||
; A0.L (input) -- pointer to string to canonize
|
||
; Opcode bit 10 -- 0 - map to upper case; 1 - case sensitive
|
||
; Opcode bit 9 -- 0 - diacritical sensitive; 1 - strip diacrits
|
||
; All registers are preserved.
|
||
; Function: UprString is a utility routine which, according to
|
||
; a pair of input booleans, strips diacritical marks
|
||
; and/or maps all characters to upper case.
|
||
;
|
||
;______________________________________________________________________
|
||
|
||
NewUprString
|
||
BSR EntString ; changed
|
||
jmpRom ROMUprStringAfterEntString
|
||
|
||
;______________________________________________________________________
|
||
;
|
||
; Routine: CmpString, RelString
|
||
; Arguments: D0.L (input) -- high-order word = string 0 length
|
||
; low-order word = string 1 length
|
||
; A0.L (input) -- pointer to string 0
|
||
; A1.L (input) -- pointer to string 1
|
||
; D0.W (output) --
|
||
; CmpString -- result code = 0, 1 for equal, unequal.
|
||
; RelString -- result code = -1, 0, 1 according as string 0
|
||
; is <, =, > than string 1, respectively.
|
||
; Opcode bit 10 -- 0 - map to upper case; 1 - case sensitive
|
||
; Opcode bit 9 -- 0 - diacritical sensitive; 1 - strip diacrits
|
||
; Pascal register conventions are observed.
|
||
;
|
||
; Calling Sequence for Pascal strings:
|
||
; LEA str0,A0
|
||
; LEA str1,A1
|
||
; MOVEQ #0,D0
|
||
; MOVE.B (A0)+,D0
|
||
; SWAP D0
|
||
; MOVE.B (A1)+,D0
|
||
; _CmpString
|
||
;
|
||
; Function: CmpString is a utility routine to compare two strings for
|
||
; equality. The strings are pointed to by A0 and A1
|
||
; on entry; the result is returned in D0.
|
||
; Two booleans determine the flavor of the compare:
|
||
; Marks --
|
||
; if set, all diacritical marks are ignored.
|
||
; Case --
|
||
; if set, all characters are mapped to upper case.
|
||
;______________________________________________________________________
|
||
|
||
;
|
||
; To expedite CmpString, test for length differences first. If they're the same,
|
||
; use the absolute value of RelString's return.
|
||
;
|
||
|
||
NewCmpString
|
||
MOVE.W D0,D2 ; str 1 length
|
||
SWAP D0 ; str 0 length
|
||
CMP.W D0,D2
|
||
BNE.S CSQuickNE
|
||
SWAP D0 ; realign for fresh start in RelString
|
||
BSR.S NewRelString ; count on CCR from last D0 store <4.6>
|
||
BPL.S @1
|
||
NEG.L D0 ; -1 ---> 1
|
||
@1
|
||
RTS
|
||
CSQuickNE
|
||
MOVEQ #1,D0 ; must differ since lengths do
|
||
RTS
|
||
|
||
|
||
;
|
||
; Register usage:
|
||
; D0 = shorter string length = loop index
|
||
; D1 = trap opcode, with embedded booleans
|
||
; D2 = string 0 input buffer
|
||
; D3 = string 1 input buffer
|
||
; D4 = -1, 0, 1 according to string lengths
|
||
;
|
||
; A0 = string 0 pointer
|
||
; A1 = string 1 pointer
|
||
;
|
||
; Output:
|
||
; D0 = -1, 0, 1
|
||
; CCR reflects D0
|
||
; D1-D2/A0-A1 trash
|
||
;
|
||
|
||
NewRelString
|
||
BSR.S EntString
|
||
jmpROM ROMRelStringAfterEntString ; <4.6>
|
||
|
||
;______________________________________________________________________
|
||
;
|
||
; Utility EntString saves regs D3-D4/A2-A3, sets up opword for quick
|
||
; test in Canonizer, and primes A2 with UpperTab and A3 with CmpTab.
|
||
; D2 is cleared for use by Canonizer.
|
||
;
|
||
; Utility ExtString cleans up and returns, leaving CCR. It is jumped to...
|
||
;______________________________________________________________________
|
||
EntString
|
||
MOVE.L (SP)+,D2 ; return address
|
||
MOVEM.L D2-D4/A2-A3,-(SP) ; return on top
|
||
LEA UpperTab,A2
|
||
jmpROM ROMEntStringAfterLEAUpperTab ; <4.6>
|
||
|
||
|
||
|
||
;
|
||
; Handy macro allows for ease in building big, regular tables.
|
||
; ASSEMBLER WON'T ALLOW EIGHTH ARGUMENT ON SAME LINE!!!!!!!!!!!!!!
|
||
;
|
||
MACRO
|
||
crow
|
||
DC.B (&Syslst[1]),( &Syslst[1]+1),( &Syslst[1]+2),( &Syslst[1]+3),( &Syslst[1]+4),( &Syslst[1]+5),( &Syslst[1]+6)
|
||
DC.B (&Syslst[1]+7)
|
||
ENDM
|
||
|
||
MACRO
|
||
dcrow
|
||
crow &Syslst[1]
|
||
crow &Syslst[1]+8
|
||
ENDM
|
||
|
||
|
||
;_________________________________________________________________________________________________________
|
||
;
|
||
; <4.6> <08/21/89 dba/pke>
|
||
;
|
||
; Note the $61 at the beginning of the lower-case letters. In Feb. 89 for the ROMs, Peter E. fixed the
|
||
; upper casing of the "`" (backquote) character. Previously, it would turn into "a" (ASCII $61).
|
||
; Unfortunately, to our dismay, all of our old HFS disks require that this bug be perpetuated forever,
|
||
; at least for the ordering of HFS names in the B-Tree, which use RelString. We also realized that
|
||
; others may be using the string traps to order internal data structure. Because of all of this, we
|
||
; are reintroducing the bug. The uppercase version of backquote is hereby declared to be lower-case a.
|
||
;
|
||
|
||
UpperTab
|
||
; Special chars, punctuation, digits, upper-case letters.
|
||
dcrow $00
|
||
dcrow $10
|
||
dcrow $20
|
||
dcrow $30
|
||
dcrow $40
|
||
dcrow $50
|
||
|
||
; Lower-case letters and some symbols.
|
||
DC.B $61,( 'A'),( 'B'),( 'C'),( 'D'),( 'E'),( 'F'),( 'G') ; fixed ` <02/29/89 pke> unfixed <4.6>
|
||
crow $48
|
||
crow $50
|
||
DC.B ('X'),( 'Y'),( 'Z'), $7B, $7C, $7D, $7E, $7F
|
||
|
||
; Accented characters.
|
||
crow $80
|
||
DC.B $CB, $89, $80, $CC, $81, $82, $83, $8F
|
||
DC.B $90, $91, $92, $93, $94, $95, $84, $97
|
||
DC.B $98, $99, $85, $CD, $9C, $9D, $9E, $86
|
||
|
||
; Symbols and upper-case AE and O-slash
|
||
dcrow $A0
|
||
|
||
; Symbols and ae, o-slash
|
||
crow $B0
|
||
DC.B $B8, $B9, $BA, $BB, $BC, $BD, $AE, $AF
|
||
|
||
; Symbols, upper A-acute, A-tilde, O-tilde, OE, and oe
|
||
crow $C0
|
||
DC.B $C8, $C9, $CA, $CB, $CC, $CD, $CE, $CE
|
||
|
||
; Symbols and undefineds. y-umlaut cannot map up.
|
||
dcrow $D0
|
||
dcrow $E0
|
||
dcrow $F0
|
||
|
||
; End of UpperTab
|
||
;_________________________________________________________________________________________________________
|
||
|
||
ENDPROC
|
||
|
||
|
||
IF doScriptMgrStr2DatFix AND (NOT installScriptMgrPtch39) THEN ; <7.8><42><50>
|
||
;============================================================================ pke <7.8>
|
||
; Patch Script Manager routines InitDateCache and String2Date for bug fixes
|
||
; needed by HyperCard.
|
||
; ----------------------------------------------------------------------------
|
||
|
||
proc
|
||
export NewInitDateCache,NewString2Date
|
||
|
||
ROMValidLong equ $1EE60 ; <7.8>
|
||
ROMBlock2String equ $1EEA0 ; <7.8>
|
||
ROMMatchString equ $1EF20 ; <7.8>
|
||
; in InitDateCache ($1EF80):
|
||
ROMAfter2ndJSRCopyArray equ $1F0E8 ; <7.8>
|
||
ROMExit equ $1F160 ; <7.8>
|
||
; in/after String2Date ($1F190):
|
||
ROMAfterDBNE equ $1F2D6 ; <7.8>
|
||
ROMDTComExit equ $1F426 ; <7.8>
|
||
ROMFixValue equ $1F46E ; <7.8>
|
||
ROMDateTimeEntry equ $1F47E ; <7.8>
|
||
|
||
WhiteSpace EQU 1 ; token number for white space
|
||
AlphaToken EQU 4 ; token number for string
|
||
NumericToken EQU 5 ; token number for number
|
||
AltNumericToken equ $B ; alternate token type for numbers
|
||
NonAlphNumToken EQU 16 ; token numbers starting here correspond to non-alpha numeric tokens
|
||
MaxTokens EQU 32 ; number of tokens for which there is space
|
||
|
||
omdy EQU 0 ; date order constants
|
||
odmy EQU 1
|
||
oymd EQU 2
|
||
|
||
Str15 EQU 16 ; length of string[15]
|
||
DayMonthLen equ 15 ; length of days and months
|
||
NumDays EQU 7 ; length of various arrays
|
||
NumMonths EQU 12
|
||
DayList EQU NumDays*Str15
|
||
MonthList EQU NumMonths*Str15
|
||
NumStrBytes EQU 300
|
||
|
||
Cache RECORD 0
|
||
version ds.w 1
|
||
CurrentDate DS LongDateRec
|
||
BaseDate DS LongDateRec
|
||
theDays DS.B DayList ; <7.8>
|
||
theMonths DS.B MonthList ; <7.8>
|
||
theEveStr DS.B Str15
|
||
theMornStr DS.B Str15
|
||
the24hrStr DS.B Str15
|
||
theTimeSep DS.W 1
|
||
theDateSep DS.W 1
|
||
theDateOrder DS.b 1
|
||
longDateOrder ds.b 1
|
||
theAbbrLen DS.W 1
|
||
TBlock DS tokenBlock
|
||
CacheSize equ *
|
||
theTimeStrings equ theEveStr
|
||
ENDR
|
||
|
||
; ----------------------------------------------------------------------------
|
||
; function InitDateCache(theCache: CachePtr): OSErr;
|
||
;
|
||
; InitDateCache will initialize the items in the DateCacheRecord pointed to by theCache^
|
||
; and set the initialized item to true
|
||
;
|
||
; The bug fixes are in the CopyArray subroutine <7.8>.
|
||
; ----------------------------------------------------------------------------
|
||
|
||
idcSaveRegs REG A2-A4/D3/d4
|
||
|
||
InitCacheRec RECORD {A6link},decr
|
||
Result DS.W 1 ; offset to function result (integer)
|
||
paramBegin EQU *
|
||
theCache DS.L 1 ; pointer to the cache record
|
||
selector ds.l 1 ; added for resource
|
||
paramEnd EQU *
|
||
return DS.L 1
|
||
A6link DS.L 1
|
||
theTokens DS.B 2*TokenRec.tokenRecSize
|
||
Intl0 DS.L 1 ; handle, not pointer
|
||
Intl1 DS.L 1 ; handle, not pointer
|
||
altSpace ds.w 1 ; use top byte
|
||
aLongDate ds LongDateTime ;
|
||
localsize EQU *
|
||
ENDR
|
||
|
||
WITH InitCacheRec,LongDateField
|
||
|
||
NewInitDateCache
|
||
LINK A6,#localsize ; Establish local frame and variables
|
||
MOVEM.L idcSaveRegs,-(SP) ; saved used registers
|
||
CLR.W Result(A6) ; clear function result
|
||
|
||
MOVE.L theCache(A6),A2 ; cache addr
|
||
|
||
move.b #' ',altSpace(a6) ; assume no alt space
|
||
|
||
sub.l #6,sp ; reserve returns
|
||
_IntlScript ; get the script
|
||
move.w #smScriptRight,-(sp) ; get flag
|
||
_GetScript ; get value
|
||
tst.l (sp)+ ; got it?
|
||
beq.s @NoAltSpace ; no
|
||
move.b #' '+$80,altSpace(a6) ; use alt space.
|
||
@NoAltSpace
|
||
|
||
WITH Cache
|
||
|
||
lea aLongDate(a6),a0 ; @temp
|
||
clr.l (a0)+ ; no high
|
||
move.l Time,(a0)+ ; low = current
|
||
pea aLongDate(a6) ; extended
|
||
pea CurrentDate(A2) ; get current date from system global time and convert to date
|
||
_LongSecs2Date
|
||
|
||
lea aLongDate(a6),a0 ; @temp
|
||
clr.l (a0)+ ; no high
|
||
clr.l (a0)+ ; low = current
|
||
pea aLongDate(a6) ; extended
|
||
pea BaseDate(A2) ; get base date and convert to date
|
||
_LongSecs2Date
|
||
|
||
; IUGetIntl(0): Handle
|
||
|
||
CLR.L -(SP)
|
||
CLR.W -(SP)
|
||
_IUGetIntl
|
||
MOVE.L (SP)+,Intl0(A6)
|
||
|
||
move.w ResErr,d0 ; did intl0 load in all right
|
||
BEQ.S GotIntl0Ok ; if so, go on
|
||
|
||
MOVE.W d0,Result(A6)
|
||
BRA Exit
|
||
|
||
GotIntl0Ok
|
||
; IUGetIntl(1): Handle
|
||
|
||
CLR.L -(SP)
|
||
MOVE.W #1,-(SP)
|
||
_IUGetIntl
|
||
MOVE.L (SP)+,Intl1(A6)
|
||
|
||
TST.W ResErr ; did intl0 load in all right
|
||
BEQ.S GetSeparators ; if so, go on
|
||
|
||
MOVE.W ResErr,Result(A6)
|
||
BRA Exit
|
||
|
||
GetSeparators
|
||
MOVE.L Intl0(A6),A3
|
||
; Lock itl0 across Block2String calls (which can now move memory)
|
||
move.l a3,a0
|
||
_MoveHHi
|
||
move.l a3,a0
|
||
_HLock
|
||
|
||
MOVE.L (A3),A3 ; now a3 is pointer to itl0
|
||
|
||
; Block2String(eveStr,theEveStr,4,true)
|
||
|
||
LEA eveStr(A3),A0 ; get international 0 record for evening string
|
||
LEA theEveStr(A2),A1
|
||
MOVEQ #4,D0
|
||
MOVE.B #1,D1
|
||
move.b altSpace(a6),d2 ; pass alt string
|
||
JsrROM ROMBlock2String ; convert packed array of char into string <7.8>
|
||
; with no leading spaces
|
||
; Block2String(mornStr,theMornStr,4,true)
|
||
|
||
LEA mornStr(A3),A0 ; get international 0 record for morning string
|
||
LEA theMornStr(A2),A1
|
||
MOVEQ #4,D0
|
||
MOVE.B #1,D1
|
||
move.b altSpace(a6),d2 ; pass alt string
|
||
JsrROM ROMBlock2String ; convert packed array of char into string <7.8>
|
||
; with no leading spaces
|
||
; Block2String(time1Stuff,the24hrStr,1,true)
|
||
|
||
LEA timeSuff(A3),A0 ; get international 0 record for 24 hour string
|
||
LEA the24hrStr(A2),A1
|
||
MOVEQ #1,D0
|
||
MOVE.B #1,D1
|
||
move.b altSpace(a6),d2 ; pass alt string
|
||
JsrROM ROMBlock2String ; convert packed array of char into string <7.8>
|
||
; with no leading spaces
|
||
|
||
MOVE.B timeSep(A3),theTimeSep(A2) ; get time separator from intl 0
|
||
MOVE.B dateOrder(A3),theDateOrder(A2)
|
||
MOVE.B dateSep(A3),(theTimeSep + 1)(A2)
|
||
|
||
; Now unlock itl0
|
||
move.l Intl0(A6),a0
|
||
_HUnlock
|
||
|
||
MOVE.L Intl1(A6),A3
|
||
|
||
; Lock itl1 across Copy Array calls; it calls Block2String, which can now move memory
|
||
move.l a3,a0
|
||
_MoveHHi
|
||
move.l a3,a0
|
||
_HLock
|
||
|
||
MOVE.L (A3),A3 ; now a3 is pointer to itl1
|
||
|
||
; Get the long date order and convert
|
||
; false => dmy, true => mdy; otherwise fancy stuff
|
||
|
||
move.l #omdy,d1 ; assume false
|
||
clr.w d0 ; wordize
|
||
move.b lngDateFmt(a3),d0 ; get long format
|
||
beq.s @GotLong ; done
|
||
move.l #odmy,d1 ; assume true
|
||
cmp.b #$FF,d0 ; true?
|
||
beq.s @GotLong ; yes, got it
|
||
|
||
; if we are looking at the long date, only the day and year are important,
|
||
; since the dayOfWeek and month are both strings. Walk through the format until
|
||
; we find either one or the other
|
||
|
||
@LongFmtLoop
|
||
move.b d0,d2 ; get bottom half-nybble
|
||
and.b #3,d2 ; got it
|
||
cmp.b #longDay,d2 ; day?
|
||
beq.s @GotLong ; yes, return #odmy
|
||
cmp.b #longYear,d2 ; year?
|
||
beq.s @LongYearFirst ; go for it
|
||
lsr.b #2,d0 ; strip bottom
|
||
bne.s @LongFmtLoop ; repeat until done
|
||
@LongYearFirst
|
||
move.l #oymd,d1 ; year first (also if none found)
|
||
|
||
@GotLong
|
||
move.b d1,longDateOrder(a2) ; set it
|
||
|
||
; continue
|
||
MOVE.B abbrLen(A3),theAbbrLen(A2) ; get abbrLen
|
||
|
||
; changed order for more convenience in the later routine
|
||
lea months(a3),a4 ; source of days
|
||
LEA theMonths(A2),a1 ; destination names of the day and months
|
||
MOVE.L #(numMonths - 1),D3 ; load day and months from intl 1 rec into space
|
||
jsr CopyArray ; copy days
|
||
|
||
lea days(a3),a4 ; source of days
|
||
LEA theDays(A2),a1 ; destination names of the day and months
|
||
MOVE.L #(numDays - 1),D3 ; load day and months from intl 1 rec into space
|
||
jsr CopyArray ; copy days
|
||
|
||
; Now continue with ROM code
|
||
JmpROM ROMAfter2ndJSRCopyArray ; <7.8>
|
||
Exit
|
||
JmpROM ROMExit ; <7.8>
|
||
|
||
; little subroutine for code savings
|
||
; a4 is source pointer
|
||
; a1 is dest pointer
|
||
; d3 is byte length
|
||
|
||
CopyArray
|
||
move.l a1,d4 ; dest ptr
|
||
|
||
@LOOP MOVE.L A4,A0 ; move string from intl 1 rec <7.8>
|
||
MOVE.L d4,A1 ; into local frame
|
||
moveq #0,d0 ; Block2String wants a long! <7.8>
|
||
MOVE.B (A0)+,D0 ; with length from first byte of string
|
||
MOVEQ #1,D1 ; with no local frame
|
||
move.b altSpace(a6),d2 ; pass alt string
|
||
JsrROM ROMBlock2String ; search <7.8>
|
||
ADD.L #Str15,d4 ; get next string to transfer
|
||
ADD.w #Str15,A4 ; into next string in local frame <7.8>
|
||
DBRA D3,@LOOP
|
||
rts
|
||
|
||
ENDWITH ; Cache
|
||
ENDWITH
|
||
|
||
; ----------------------------------------------------------------------------
|
||
;function String2Date( textPtr: Ptr;
|
||
; textLen: longint;
|
||
; theCache: DateCachePtr;
|
||
; var lengthUsed: longint;
|
||
; var DateTime: LongDateRec): Integer;
|
||
;
|
||
; String2Date will look for a date in the text given it according to the international
|
||
; resource format. Using the Tokenizer routine it will look for a dayofWeek (which will
|
||
; be a string), a month (either a string or a number) and a day and year (both numbers).
|
||
; If the month is a number, order is decided by the ShortDate format in INTL 0; otherwise
|
||
; String2Date uses a table. Note if only two numbers are found they are assumed to be day
|
||
; and month. If one number is found it is assumed to be a date. Missing fields are
|
||
; filled in by the current date and time
|
||
;
|
||
; Register Usage
|
||
;
|
||
; A2 - Work register D3 - loop control register
|
||
; A3 - Work register D4 - MonthFound
|
||
; A4 - Cache Addr D5 - ResultNum
|
||
; D6 - AbbrLen
|
||
; D7 - NumDelimsFound
|
||
;
|
||
; The bug fixes are: É <7.8>
|
||
; ----------------------------------------------------------------------------
|
||
|
||
s2dSaveRegs REG D3-D7/A2-a4 ; removed a5
|
||
|
||
DateFrame RECORD {A6link},decr
|
||
Result DS.W 1 ; offset to function result (integer)
|
||
paramBegin EQU *
|
||
textPtr DS.L 1 ; offset to Date2Time's paramters
|
||
textLen DS.L 1
|
||
theCache DS.L 1 ; @DateCacheRecord
|
||
RestofText DS.L 1 ; @Longint
|
||
DateTime DS.L 1 ; @LongDateRec
|
||
selector ds.l 1 ; added for resource
|
||
paramEnd EQU *
|
||
return DS.L 1
|
||
A6link DS.L 1
|
||
theTokens DS.B MaxTokens*TokenRec.tokenRecSize ; storage for tokens found by tokenizer
|
||
theDate DS LongDateRec ; date time rec
|
||
results DS.W 3 ; three temporary results
|
||
myDateOrder DS.W 1
|
||
DayFound DS.W 1
|
||
lastItemSep DS.W 1
|
||
lastToken DS.W 1
|
||
lastTokenAddr DS.L 1
|
||
lastExToken DS.W 1
|
||
dummyLongDate ds LongDateTime
|
||
stringStorage DS.B NumStrBytes
|
||
localsize EQU *
|
||
ENDR
|
||
|
||
WITH DateFrame
|
||
With Cache,LongDateField
|
||
|
||
NewString2Date
|
||
LINK A6,#localsize ; Establish local frame and variables
|
||
MOVEM.L s2dSaveRegs,-(SP) ; saved used registers
|
||
JsrROM ROMDateTimeEntry ; initialize & call _IntlTokenize
|
||
|
||
; Note that DateTimeEntry also does the following:
|
||
; 1. moves theCache(a6) into a4
|
||
; 2. moves TheTokens(a6) into a3
|
||
; 3. sets result(a6)
|
||
; 4. clears D7,D6; sets D5.L = -1
|
||
; 5. after IntlTokenize, sets D3= number of tokens - 1
|
||
|
||
tst.w result(a6) ; entry failed?
|
||
bne DTComExit ; bail if so
|
||
|
||
; specific stuff
|
||
|
||
MOVEQ #-1,D4 ; initialize MonthFound to -1
|
||
CLR.W DayFound(A6)
|
||
LEA CurrentDate(A4),A1 ; source
|
||
LEA theDate(A6),A0 ;
|
||
MOVE.L (A1)+,(A0)+ ; era, year
|
||
MOVE.L (A1)+,(A0)+ ; month, day
|
||
MOVE.L (A1)+,(A0)+ ; hour, minute
|
||
move.w (a1)+,(a0)+ ; second
|
||
CLR.W (A0)+ ; clear out dayOfWeek. Will either be set by user or be set
|
||
; in the course of the validity check of the date
|
||
MOVE.B theAbbrLen(A4),D6
|
||
|
||
WITH TokenRec
|
||
|
||
@TokenLoop
|
||
MOVE.W theToken(A3),D1 ; get token code from TokenRec record at (A3)
|
||
CMP.W #NonAlphNumToken,D1 ; is it a separator
|
||
BGE.S @FoundSeparator
|
||
SUB.W #WhiteSpace,D1 ; was it a white space?
|
||
BEQ @TokenLoopEnd ; ignore
|
||
SUBQ.W #(AlphaToken - WhiteSpace),D1 ; is it an alpha token?
|
||
beq.s @FoundAlpha
|
||
SUBQ.W #(NumericToken - AlphaToken),D1 ; is it a number token?
|
||
BEQ.S @NumberToken
|
||
SUBQ.W #(AltNumericToken - NumericToken),D1 ; is it a number token?
|
||
BEQ.S @NumberToken ;
|
||
BRA @TokenLoopEnd ; ignore any other characters
|
||
|
||
@FoundSeparator
|
||
TST.B D7 ; possible separator. Has a separator already been found
|
||
BEQ.S @OneDelimFound ; no, so no error yet
|
||
OR.W #TooManySeps,Result(A6) ; yes, so now we have too many separators
|
||
|
||
@OneDelimFound
|
||
ADDQ.B #1,D7 ; record separator found
|
||
TST.w D5 ; is this after the first number loaded? (.w) <1/5/88med>
|
||
BMI @TokenLoopEnd ; if we have not reached a number yet go on
|
||
BNE.S @CheckDateSep ; if we loaded in a number then check consistency
|
||
|
||
MOVE.W D1,lastItemSep(A6) ; otherwise update lastItemSep with just found separator
|
||
BRA @TokenLoopEnd
|
||
|
||
@CheckDateSep
|
||
CMP.W lastItemSep(A6),D1 ; are they consistent
|
||
BEQ @TokenLoopEnd ; if yes, than go on
|
||
|
||
OR.W #SepNotIntlSep+sepNotConsistent,Result(A6) ; record warning
|
||
BRA @TokenLoopEnd
|
||
|
||
@NumberToken
|
||
; check for numbers separated only by white space
|
||
tst.w d7 ; got a separator?
|
||
bne.s @1 ; yes
|
||
tst.w d5 ; first number?
|
||
blt.s @1 ; yes, skip
|
||
bne.s @0 ; have 1 number
|
||
move.w #WhiteSpace,lastItemSep(A6) ; set separator
|
||
bra.s @1 ; continue
|
||
@0
|
||
cmp.w #WhiteSpace,lastItemSep(a6) ; same?
|
||
beq.s @1 ; yes, continue
|
||
or.w #SepNotIntlSep+sepNotConsistent,Result(A6) ; record warning
|
||
@1
|
||
; end of white space check
|
||
|
||
CLR.L D7 ; clear out past separators
|
||
CMP.W #2,D5 ; make sure that results array is not full
|
||
BGE @ExtrnsToken ; if full, record warning and search <7.8>
|
||
; for final string (remove .s)
|
||
|
||
; ValidLong(position,textLength): longint
|
||
|
||
MOVE.L stringPosition(A3),A0
|
||
JsrROM ROMValidLong ; get number in text at TokenRec.position <7.8>
|
||
BMI DTComExit
|
||
|
||
JsrROM ROMFixValue ; <7.8>
|
||
bra @TokenRecognized ; get next token (remove .s) <7.8>
|
||
|
||
@FoundAlpha
|
||
CLR.L D7 ; clear out past separators
|
||
|
||
; UprString(newTextPtr,AbbrLen) ; and make it uppercase for case insensitive search
|
||
|
||
MOVE.L stringPosition(A3),A2
|
||
ADDQ.L #1,A2
|
||
MOVE.L A2,A0
|
||
MOVE.L length(A3),D0 ; use real length
|
||
|
||
_UpperText ; _LwrString with uppercase function <39><45>
|
||
|
||
TST.W D4
|
||
BPL.S @SearchForDay ; <7.8>
|
||
|
||
; MatchString(newTextPtr,AbbrLen,@months,15,12): integer
|
||
|
||
CLR.W -(SP) ; attempt to find a day/month string which matches alpha token
|
||
MOVE.L A2,-(SP)
|
||
MOVE.W length+2(a3),-(SP) ; push length as integer
|
||
MOVE.W D6,-(SP) ; push minlen as integer
|
||
PEA theDays(A4) ; <7.8>
|
||
MOVE.W #DayMonthLen,-(SP)
|
||
MOVE.W #NumMonths+NumDays,-(SP) ; check for both at once
|
||
JsrROM ROMMatchString ; <7.8>
|
||
MOVE.W (SP)+,D2 ; save in D2
|
||
BLE.S @ExtrnsToken ; checking both
|
||
|
||
; decide between days and months
|
||
|
||
sub.w #NumDays,d2 ; months?
|
||
ble.s @CheckForDay ; no, do days
|
||
|
||
; got a month
|
||
CMP.W #2,D5 ; is result array already full?
|
||
BGE.S @ExtrnsToken ; if so, then its not a needed token
|
||
|
||
ADDQ.W #1,D5 ; is in range, result is not full and string
|
||
MOVE.W D5,D1 ; did not match as a day
|
||
ADD.W D1,D1 ; double index for integer array
|
||
LEA results(A6),A1 ; ResultNum:= ResultNum + 1
|
||
MOVE.W D2,(A1,D1.W) ; results[ResultNum]:= match result
|
||
MOVE.W D5,D4 ; MonthFound:= resultNum
|
||
BRA.S @TokenRecognized
|
||
|
||
; if day not found yet, we need to see if current string matches a day <7.8>
|
||
@SearchForDay
|
||
TST.B DayFound(a6) ; have we found one yet?
|
||
BNE.S @ExtrnsToken ; day already found, record warning
|
||
|
||
CLR.W -(SP) ; attempt to find a day string which matches alpha token
|
||
MOVE.L A2,-(SP)
|
||
MOVE.W length+2(a3),-(SP) ; push length as integer
|
||
MOVE.W D6,-(SP) ; push minlen as integer
|
||
PEA theDays(A4)
|
||
MOVE.W #DayMonthLen,-(SP)
|
||
MOVE.W #NumDays,-(SP) ; just check days this time
|
||
JsrROM ROMMatchString ; <7.8>
|
||
MOVE.W (SP)+,D2 ; save in D2
|
||
BLE.S @ExtrnsToken ; checking both
|
||
|
||
BRA.S @HaveDay
|
||
|
||
@CheckForDay
|
||
TST.B DayFound(a6) ; off of a6!
|
||
BNE.S @ExtrnsToken ; day already found, record warning
|
||
|
||
add.w #NumDays,d2 ; restore days <7.8>
|
||
@HaveDay ; <7.8>
|
||
ST DayFound(A6) ; record that day was found <7.8>
|
||
|
||
MOVE.W D2,theDate.dayOfWeek(A6) ; otherwise, load dayOfWeek into date time record
|
||
|
||
TST.W D5 ; is dayOfWeek between two numbers (.w)
|
||
BMI.S @NoWarning ; if no number has been found yet, go on
|
||
OR.W #fieldOrderNotIntl,Result(A6) ; record warning
|
||
@NoWarning
|
||
BRA.S @TokenRecognized
|
||
|
||
@ExtrnsToken
|
||
TST.W lastExToken(A6) ; is this the first extraneous token found?
|
||
BPL.S @TokenLoopEnd ; no, go on
|
||
|
||
MOVE.W D3,lastExToken(A6) ; a string which we don't recognize has been found
|
||
BRA.S @TokenLoopEnd ; record warning and go on
|
||
|
||
@TokenRecognized
|
||
MOVE.W D3,lastToken(A6)
|
||
MOVE.L A3,lastTokenAddr(A6) ; save loop and token addr for later use
|
||
|
||
@TokenLoopEnd
|
||
ADD.L #tokenRecSize,A3 ; add size of TokenRec record to A3 to get next token
|
||
CMP.W #2,D5 ; if the result array full (.w)
|
||
SGE D0
|
||
AND.B DayFound(A6),D0 ; and dayofWeek string been found
|
||
DBNE D3,@TokenLoop ; then stop loop, otherwise go until all tokens are looked at
|
||
|
||
JmpROM ROMAfterDBNE
|
||
|
||
DTComExit
|
||
JmpROM ROMDTComExit
|
||
|
||
endproc
|
||
|
||
ENDIF
|
||
|
||
IF doScriptMgrRstKCHRFix AND (NOT installScriptMgrPtch39) THEN ; <8.0><42><50>
|
||
;============================================================================ pke <8.0>
|
||
; Tail patch on _GetIndADB to fix bug in Script Manager ResetKCHR routine
|
||
; called by SwapKybd: it clears ADB keyboard driver dead state as a word,
|
||
; should be a long.
|
||
; ----------------------------------------------------------------------------
|
||
|
||
proc
|
||
export ptchGetIndADB
|
||
|
||
ROMAfterGetIndADB equ $1E048
|
||
ROMAfterClrDeadKey equ $1E058
|
||
ROM@1dbra equ $1E064
|
||
|
||
|
||
ptchGetIndADB
|
||
CmpRA ROMAfterGetIndADB,OSTrapReturnAddressDepth(sp) ; From ResetKCHR?
|
||
bne.s @0 ; if not, just continue with trap
|
||
lea ptchResetKCHR,a1 ; a1 is not a param for GetIndADB
|
||
move.l a1,OSTrapReturnAddressDepth(sp) ; so trap returns to patch, not ROM
|
||
@0 BackToTrap oldGetIndADB ; now get on with the trap
|
||
|
||
|
||
; When we reach the patch below, we are in ResetKCHR just after the _GetIndADB
|
||
|
||
rkRecord record {a6link},decr
|
||
rkArgs equ *-8 ; size of arguments.
|
||
pointer ds.l 1 ; new KCHR pointer.
|
||
return ds.l 1 ; return address.
|
||
a6link ds.l 1 ; old a6 register.
|
||
adb ds ADBDataBlock ; ADB data structure.
|
||
oldKeyboard ds.l 1 ; old keyboard pointer
|
||
rkLocals equ * ; size of local variables.
|
||
endr
|
||
|
||
ptchResetKCHR
|
||
with rkRecord
|
||
|
||
cmp.b #kybdADBAddr,adb.origADBAddr(a6) ; is it a keyboard?
|
||
bne.s @1 ; no -> skip it.
|
||
move.l adb.dbDataAreaAddr(a6),a0 ; load data area pointer.
|
||
clr.l KybdDriverData.deadKey(a0) ; clear dead state - long! <8.0>
|
||
JmpROM ROMAfterClrDeadKey ; <8.0>
|
||
|
||
@1 JmpROM ROM@1dbra ; <8.0>
|
||
|
||
endwith
|
||
endproc
|
||
|
||
ENDIF
|
||
|
||
IF doScriptMgrLwrString2 AND (NOT installScriptMgrPtch27) THEN ; <8.5><50>
|
||
;============================================================================ pke <8.5>
|
||
; Patch LwrString to handle 2-byte chars via Transliterate.
|
||
; ----------------------------------------------------------------------------
|
||
; routine: LwrString
|
||
; input: a0 textPtr
|
||
; d0.w length
|
||
; d1.w trap word; the following bits are significant in 7.0 only:
|
||
; Opcode bits
|
||
; 10 9 Function
|
||
; -- -- --------
|
||
; 0 0 convert to lower-case
|
||
; 0 1 strip diacritics
|
||
; 1 0 convert to upper-case
|
||
; 1 1 convert to upper-case and strip diacritics
|
||
; output: d0.w error
|
||
; function: Change text pointed to by a0 according to opcode bits. Before 7.0, we
|
||
; just assume that these bits are 0 and act accordingly.
|
||
; ----------------------------------------------------------------------------
|
||
|
||
proc
|
||
export ptchLwrString
|
||
|
||
lwrTrFrame record {a6link},decr
|
||
return ds.l 1 ; return address
|
||
a6link ds.l 1 ; link pointer
|
||
sourcePtr ds.l 1 ; orig source ptr
|
||
sourceLen ds.l 1 ; orig source len
|
||
sourceHndl ds.l 1 ; new handle with copy of source
|
||
destHndl ds.l 1 ; new handle for transliterate result
|
||
errCode ds.w 1 ; err code to be returned in d0
|
||
lwrTrLocals equ * ; size of locals
|
||
endr
|
||
|
||
; ----------------------------------------------------------------------------
|
||
; NOTE: For 2-byte scripts, we need to call Transliterate. So, the first thing to
|
||
; do is figure out what script we're in. We also test for length <= 0 (tests >32K).
|
||
; ----------------------------------------------------------------------------
|
||
|
||
ptchLwrString
|
||
ext.l d0 ; as fast as tst.w and we need ext.l later
|
||
ble lwrRTS ; if bad length, quit
|
||
movem.l a0/d0/d1,-(sp) ; save important registers
|
||
subq.l #2,sp ; make room for return
|
||
_FontScript ; find script of port
|
||
move.w (sp)+,d2 ; pop it into d2
|
||
movem.l (sp)+,a0/d0/d1 ; restore important registers
|
||
|
||
; ----------------------------------------------------------------------------
|
||
; Here we make use of the fact that a word redraw flag of 1 (or anything >0)
|
||
; indicates a 2-byte script.
|
||
; ----------------------------------------------------------------------------
|
||
|
||
with SMgrRecord,ScriptRecord
|
||
lsl.w #2,d2 ; make script code a long offset
|
||
move.l IntlSpec,a1 ; get SMgrRecord pointer
|
||
move.l smgrEntry(a1,d2.w),d2 ; get ScriptRecord pointer
|
||
beq lwrRTS ; if nil (script not installed), do nothing
|
||
move.l d2,a1
|
||
tst.b scriptEnabled(a1) ; is script enabled?
|
||
beq lwrRTS ; if not, do nothing
|
||
tst.b scriptRedraw(a1) ; is it a 2-byte script?
|
||
ble not2Byte ; if not, go use normal LwrString
|
||
endwith
|
||
|
||
; ----------------------------------------------------------------------------
|
||
; OK, we need to set up for Transliterate: set up source & dest handles
|
||
; ----------------------------------------------------------------------------
|
||
|
||
with lwrTrFrame
|
||
link a6,#lwrTrLocals ; create local storage
|
||
move.l a0,sourcePtr(a6) ; save source ptr
|
||
move.l d0,sourceLen(a6) ; save length
|
||
_PtrToHand ; make new handle containing copy of text
|
||
move.w d0,errCode(a6) ; save err code
|
||
bne.s lwrTrUnlk ; if error in PtrToHand, quit
|
||
move.l a0,sourceHndl(a6) ; save new source handle
|
||
move.l sourceLen(a6),d0 ; get length again
|
||
_NewHandle ; make new handle with random contents
|
||
move.w d0,errCode(a6) ; save err code
|
||
bne.s lwrTrDisp1Hndl ; if error in NewHandle, quit
|
||
|
||
; ----------------------------------------------------------------------------
|
||
; Now do Transliterate and check result: dest length should equal source length
|
||
; ----------------------------------------------------------------------------
|
||
|
||
move.l a0,destHndl(a6) ; save new dest handle
|
||
subq.l #2,sp ; space for Transliterate error code
|
||
move.l sourceHndl(a6),-(sp) ; push source handle
|
||
move.l a0,-(sp) ; push dest handle (still in a0)
|
||
move.w #smTransLower+smTransAscii,-(sp) ; lower-case conversion, target=Roman
|
||
move.l #smMaskAscii,-(sp) ; convert Roman only
|
||
_Transliterate
|
||
move.w (sp)+,errCode(a6) ; save error code
|
||
bne.s lwrTrDisp2Hndl ; if error in Transliterate, quit
|
||
move.l destHndl(a6),a0 ; now check resultÉ
|
||
_GetHandleSize
|
||
move.w d0,errCode(a6) ; save err code
|
||
tst.l d0 ; .l, because the result is really a long
|
||
blt.s lwrTrDisp2Hndl ; if error in GetHandleSize, quit
|
||
move.w #-1,errCode(a6) ; assume len err; need a better err code!
|
||
cmp.l sourceLen(a6),d0 ; should be same as source len
|
||
bne.s lwrTrDisp2Hndl ; if not, set err and bail
|
||
|
||
; ----------------------------------------------------------------------------
|
||
; Copy result (destHndl) to original text buffer (sourcePtr).
|
||
; NOTE: For large text blocks, _BlockMove might be faster than this loop.
|
||
; ----------------------------------------------------------------------------
|
||
|
||
move.l destHndl(a6),a0 ; get dest handle andÉ
|
||
move.l (a0),a0 ; deref it to get source ptr for this copy
|
||
move.l sourcePtr(a6),a1 ; old source ptr is dest for this copy
|
||
move.l sourceLen(a6),d0 ; length for copy (we know it is >= 1)
|
||
subq.l #1,d0 ; set up for dbra
|
||
@1 move.b (a0)+,(a1)+ ; copy a byte
|
||
dbra d0,@1 ; loop till done
|
||
clr.w errCode(a6) ; no errors!
|
||
|
||
; ----------------------------------------------------------------------------
|
||
; Exits - need to dispose of handles we created
|
||
; ----------------------------------------------------------------------------
|
||
|
||
lwrTrDisp2Hndl
|
||
move.l destHndl(a6),a0 ;
|
||
_DisposHandle ;
|
||
lwrTrDisp1Hndl
|
||
move.l sourceHndl(a6),a0 ;
|
||
_DisposHandle ;
|
||
lwrTrUnlk
|
||
move.w errCode(a6),d0 ; set err code
|
||
unlk a6 ;
|
||
rts
|
||
endwith
|
||
|
||
lwrRTS
|
||
clr.w d0
|
||
rts
|
||
|
||
; ----------------------------------------------------------------------------
|
||
; This is not a 2-byte script, just use old LwrString.
|
||
; ----------------------------------------------------------------------------
|
||
not2Byte
|
||
BackToTrap oldLwrString ;
|
||
endproc
|
||
|
||
ENDIF
|
||
|
||
;_______________________________________________________________________
|
||
; <7.1><8.7><41><81><123><125><126><128><135><137> Async Serial Driver Patch
|
||
; <4><5>
|
||
;
|
||
; Start of patch code for fix of bugs in the serial driver
|
||
; introduced into the aurora ROM (and hence the F19 overpatch ROM) by the
|
||
; port arbitration code, which was accidently included in those ROMS.
|
||
;
|
||
; The patch is installed in a patch vector for the async driver.
|
||
; Note the 'simple' come-from patching mechanism has been really hosed by the
|
||
; addition of the pic chip code; now we have to include all that code in the
|
||
; patch. Something to watch for when fixing the ROM driver.
|
||
;
|
||
; Needed to include all code which jumped TO the ExtSts interrupt handler.
|
||
;
|
||
; Traps patched: -- The AsyncVector, which is in the middle of the OS ToolTable
|
||
; is patched, Trap number = $A0BE
|
||
; -- all the PIC driver headers patched. <41>
|
||
;
|
||
;
|
||
; HISTORY:
|
||
; <7.1> 10/2/89 patch ExtAIntHnd and ExtBIntHnd
|
||
; <8.7> check SCCIOPFlag now instead of PRAM to determine which driver to load.
|
||
; changed sense of bypass bit to agree with new ROM definition.
|
||
; <41> fixed <8.7> to use the patch macros. Also added in patch for the
|
||
; IOPSerialDriver for the prime code. As a result, had to patch ALL
|
||
; the IOP driver headers. yuck.
|
||
; <81> added VM support for the SerSetBuf control call.
|
||
; <123> added nike printer support:
|
||
; patched control call 16 in bypass driver to use bit 6 for setting
|
||
; external/internal clocking modes.
|
||
; Patched both bypass and IOP code to add status call to return version.
|
||
; Patched InitSCC routine in bypass driver to use this RAM-based table so
|
||
; that clocking mode is now variable instead of hard-wired to internal only.
|
||
; -- set clock divide to 1 instead of 16 for external clocking
|
||
; -- clear HWHS enable since we can't clock and handshake on same line
|
||
; Patched bypass mode driver to set bit 3 of AsyncErr if break rcvd.
|
||
; <125> We patch all the bypass driver headers (iop headers are already patched)
|
||
; so that we can put a signature word before each header that we can use
|
||
; to identify ourselves as the Apple async serial driver. We do this
|
||
; right now so that that our linked patch on Open (in Serialpatches.a) will
|
||
; not stomp the version number of some third party driver that sticks them-
|
||
; selves into our spot in the unit table. I think this idea will come in
|
||
; handy later as well.
|
||
; I think i'll use the signature word 'wong'.
|
||
; <126> fixed a bug in EXTSTS interrupt handler for port A. Because of the BAP
|
||
; stuff, AInDCE no longer has a valid ptr the .Ain driver's DCE. We solve
|
||
; the problem the same way we did in the port B code, by getting the DCE
|
||
; ptr straight from the unit table.
|
||
; <127> Fixed a bug in the External Status interrupt handler. On
|
||
; port A we crashed on receiving a break if a read was pending
|
||
; because we weren't getting the .Ain DCE ptr properly. Now we get
|
||
; the DCE ptr directly from the Unit table, just like for port B.
|
||
; <129> Fixed bug in external clock stuff that was causing us to disable
|
||
; internal clocking on both ports if we were trying to do external
|
||
; clocking on just one. So Nike would print but Tabasco would just
|
||
; sit there. The fix was to set clocking params at each time we go
|
||
; thru InitSCC, rather than just once during the external clocking
|
||
; control call. This way even tho the ports share the InitSCCTable,
|
||
; we set the Table properly by keying off of the value in CtlOptions
|
||
; variable, which they don't share.
|
||
; <135> Status call 9 and $8000 return fixed version equate instead of
|
||
; what's in the DCE. Fixed SerSetBuff (control call 9) to not sign
|
||
; extend the buffer count.
|
||
; <137> Fixed bug in IOP code that caused SerSetBuff to fail for zero size
|
||
; buffer. Wasn't clearing upper word of count passed to UnholdMemory.
|
||
; <4> patched Rx and SCx interrupt handlers to help thruput on Apollo and TIM LC
|
||
; <5> patched SCx interrupt handler to fix the StyleWriter bug. On faster
|
||
; machines we are able to send out a byte fast enough after the TBE bit
|
||
; in RR0 gets set that the byte gets written before the TBE interrupt
|
||
; is generated. Instead of just not generating the interrupt, the SCC goes
|
||
; ahead and generates it, but changes the interrupt source code to read
|
||
; 'no interrupt' instead of 'TBE'. This 'no interrupt' code is identical
|
||
; to the 'Special Condition on port B' code, which was the source of our
|
||
; problem. Fix is to just exit SCIntHnd if no special condition bits are
|
||
; set.
|
||
;
|
||
;_______________________________________________________________________
|
||
|
||
AsyncPatch proc
|
||
export SerialPatch
|
||
;
|
||
; equates
|
||
;
|
||
PortAVars EQU SerialVars ; serial chan A variables and buffer
|
||
SerialVers EQU 5 ; current version 3/91 <135>
|
||
|
||
;
|
||
; Bypass driver var offsets
|
||
;
|
||
|
||
OutDCE EQU 0 ;(4) long DCE pointer for output driver
|
||
SCCOffset EQU 4 ;(2) word of SCC offset . . .
|
||
|
||
InBufPtr EQU 6 ;(4) pointer to local input buffer
|
||
BufSize EQU 10 ;(2) size of local input buffer
|
||
BufLow EQU 12 ;(2) low buf byte count to send XOn
|
||
BufHigh EQU 14 ;(2) bytes from end of buffer to send XOff
|
||
|
||
SWHS EQU 16 ;(1) software handshake enable
|
||
HWHS EQU 17 ;(1) hardware handshake enable
|
||
XONChar EQU 18 ;(1) input char which continues output (SWHS)
|
||
XOFFChar EQU 19 ;(1) input char which stops output
|
||
|
||
Options EQU 20 ;(1) bit 4 = abort on parity error
|
||
; bit 5 = abort on overrun
|
||
; bit 6 = abort on framing error
|
||
PostOptions EQU 21 ;(1) bit 7=1 enables posting break changes
|
||
; bit 5=1 enables posting handshake changes
|
||
InSWHS EQU 22 ;(1) input XOn/XOff flow control enable
|
||
InHWHS EQU 23 ;(1) input RTS (DTR) flow ctl enb <14Oct85>
|
||
|
||
AsyncErr EQU 24 ;(1) error indications (cumulative)
|
||
SoftOR EQU 0 ; bit 0 = soft overrun
|
||
; bit 4 = parity error
|
||
; bit 5 = overrun error
|
||
; bit 6 = framing error
|
||
|
||
FlowOff EQU 25 ;(1) $80 = input flow shut off by XOff, $40 by DTR
|
||
ReadCmd EQU 26 ;(1) FF = read command pending
|
||
WriteCmd EQU 27 ;(1) FF = write command pending
|
||
CTSFlag EQU 28 ;(1) FF = CTS asserted
|
||
XOFFlag EQU 29 ;(1) FF = XOFF pending
|
||
LastWR5 EQU 30 ;(1) WR5 value with last DTR state <14Oct85>
|
||
DTRNegVal EQU 31 ;(1) WR5 value used to negate DTR <14Oct85>
|
||
|
||
SCCReset EQU 32 ;(1) WR9 value for reset
|
||
|
||
StopBits EQU 33 ;(1) stop bits/parity option (WR4 value)
|
||
WR1AVal EQU 34 ;(1) first WR1 value to write
|
||
WR3AVal EQU 35 ;(1) first WR3 value to write
|
||
WR5AVal EQU 36 ;(1) first WR5 value to write
|
||
BaudLoCnst EQU 37 ;(2) 2 byte baud rate constant (WR12-13)
|
||
BaudHiCnst EQU 38
|
||
RcvrBits EQU 39 ;(1) 1 byte receiver bits/char (WR3 value)
|
||
XmitBits EQU 40 ;(1) 1 byte xmitter bits/char (WR5 value)
|
||
WReqPin EQU 41 ;(1) w/req pin state (WR1 value)
|
||
lastSetup EQU 42 ;(2) last SCC init values . . .
|
||
|
||
BufIndex EQU 44 ;(2) index into local buffer (insert)
|
||
BufOutdex EQU 46 ;(2) index into local buffer (remove)
|
||
LocalBuf EQU 48 ;(64) local buffer for input chars
|
||
|
||
LclBufSize EQU 64 ; default input buffer size = 64 bytes
|
||
HSCount EQU 112 ;(2) count of CTS pulses in VBL time (clk detect) <14Oct85>
|
||
LastTime EQU 114 ;(4) ticks time of last CTS pulse (clk detect) <14Oct85>
|
||
|
||
SendXOnff EQU 118 ;(1) flag to xmit logic to send XOn/XOff <14Oct85>
|
||
CharMask EQU 119 ;(1) $1F,$3F,$7F, or $FF mask for input chars <14Oct85>
|
||
|
||
PEChar EQU 120 ;(1) char to change incoming parity errors to <14Oct85>
|
||
AltChar EQU 121 ;(1) char to change incoming PEChars to <14Oct85>
|
||
|
||
InSWHS1 EQU 122 ;(1) saved InSWHS state <14Oct85>
|
||
CtlOptions EQU 123 ;(1) bits 0-6=0 (reserved). bit 7=1 to leave <14Oct85>
|
||
; DTR state unchanged at close.
|
||
SaveExInt EQU 124 ;(4) saved Ext int vector <14Oct85>
|
||
SaveTxInt EQU 128 ;(4) saved TxD int vector <14Oct85>
|
||
SaveRxInt EQU 132 ;(4) saved RxD int vector <14Oct85>
|
||
SaveSxInt EQU 136 ;(4) saved Special Rx int vector <14Oct85>
|
||
InDCE EQU 140
|
||
|
||
VarSize EQU 144 ; output driver storage size
|
||
LclVarSize EQU 144 ; output driver storage size
|
||
|
||
;
|
||
; PIC driver var offsets and misc equ
|
||
;
|
||
PICOpenFlag EQU 0 ; marks if driver is open
|
||
OpenMsgPB EQU 22
|
||
EventMsgPB EQU 106
|
||
OpenMsg EQU 270
|
||
PICInBufPtr EQU 368 ; ptr to current input buffer
|
||
PICBufSize EQU 372 ; size of current input buffer
|
||
PICBufIndex EQU 374 ; index for putting bytes into input buffer
|
||
PICBufOutdex EQU 376 ; index for taking bytes out of input buffer
|
||
PICLocalBuf EQU 378 ; ptr to driver's local buffer
|
||
|
||
; General Equates for message fields
|
||
Results Equ 0 ;(1) Message return code
|
||
OpCode Equ Results+1 ;(1) Some messages slots are shared
|
||
CloseOpCode Equ 2; Close
|
||
|
||
;____________________________________________________________________
|
||
;
|
||
; ROM address offsets
|
||
;
|
||
;____________________________________________________________________
|
||
|
||
; bypass driver ROM entrypoint addresses <125>
|
||
;port A
|
||
ROM_AInEntryOpen EQU $6ac2a
|
||
ROM_AInEntryClose EQU $6af82
|
||
ROM_AInEntryPrime EQU $6b2a8
|
||
|
||
ROM_AOutEntryOpen EQU $6acf2
|
||
ROM_AOutEntryClose EQU $6af0e
|
||
ROM_AOutEntryPrime EQU $6b1ec
|
||
|
||
ROM_AEntryControl EQU $6b002
|
||
ROM_AEntryStatus EQU $6afac
|
||
|
||
;Port B
|
||
ROM_BInEntryOpen EQU $6ac30
|
||
ROM_BInEntryClose EQU $6af82
|
||
ROM_BInEntryPrime EQU $6b2ae
|
||
|
||
ROM_BOutEntryOpen EQU $6ad22
|
||
ROM_BOutEntryClose EQU $6af22
|
||
ROM_BOutEntryPrime EQU $6b1f2
|
||
|
||
ROM_BEntryControl EQU $6b008
|
||
ROM_BEntryStatus EQU $6afb2
|
||
|
||
|
||
; Open patch equates for bypass driver
|
||
|
||
fromAOutOpen EQU $0006B542 ; at end of drvr, in IOP stuff (ChkConfig called there)
|
||
fromBOutOpen EQU $0006B550
|
||
fromAInOpen EQU $0006B55E
|
||
fromBInOpen EQU $0006B56C
|
||
fromControl EQU $6B01a
|
||
fromClose EQU $6af3e
|
||
fromStatus EQU $6afc4
|
||
fromInitSCC EQU $6aeb8
|
||
|
||
backToAOutOpen EQU $0006AD12 ; returning to finish up Open routines in ROM
|
||
backToBOutOpen EQU $0006AD44
|
||
PlugInDrvr EQU $0006B594 ; plug header addr into DCE and continue
|
||
backToInOpen EQU $0006ac34 ; finish In Open routines in ROM
|
||
|
||
ROM_PollDtain EQU $0006B372 ; rom routines addresses we must push on the stack
|
||
ROM_SCAIntHnd EQU $0006B466
|
||
ROM_SCBIntHnd EQU $0006B45C
|
||
ROM_RAIntHnd EQU $0006B3B0
|
||
ROM_RBIntHnd EQU $0006B3A6
|
||
ROM_TAIntHnd EQU $0006B276
|
||
ROM_TBIntHnd EQU $0006B26C
|
||
|
||
|
||
ROM_AsyncAIn EQU $0006abca ; ROM header addresses for byass drivers
|
||
ROM_AsyncAOut EQU $0006ABE2
|
||
ROM_AsyncBIn EQU $0006abfa
|
||
ROM_AsyncBOut EQU $0006AC12
|
||
|
||
; Control patch equates for bypass driver
|
||
|
||
backToControl EQU $6b02c ; for fixing control calls
|
||
ROM_CtlGood EQU $6b062
|
||
ROM_CtlExit EQU $6b064
|
||
FinishCall9 EQU $6b0c0
|
||
InitSCC EQU $6aea8
|
||
|
||
; Close patch equates for bypass driver
|
||
SyncOutput EQU $6af86
|
||
InitSCC1 EQU $6aeae
|
||
backToClose EQU $6af64
|
||
ResetData EQU $6aefe
|
||
ResetLth EQU $10
|
||
|
||
; InitSCC patch equates for bypass driver
|
||
backToInitSCC EQU $6aeb8
|
||
initData EQU $6ae74
|
||
|
||
; Status patch equates for bypass driver
|
||
backToStatus EQU $6afde
|
||
|
||
|
||
; Interrupt Handler equates for the bypass driver
|
||
|
||
; External/Status interrupt handler equates
|
||
ToContOut1 EQU $0006B29C ; return to finish up interrupt routines in ROM
|
||
ToRdReqDone EQU $0006B4B6
|
||
ToCtlSet EQU $0006B14C
|
||
|
||
; Rx interrupt handler equates
|
||
ROM_PutInOurBuf EQU $6b400
|
||
ROM_toStash EQU $6b312
|
||
ROM_GoodFinish EQU $6b234
|
||
|
||
; SC interrupt handler equates
|
||
ROM_abortReq EQU $6b4ae
|
||
|
||
; PIC driver ROM entrypoint addresses
|
||
; (note some are here for documentation purposes only)
|
||
|
||
ROM_PICAInOpen EQU $0006B60A ; .AIn
|
||
ROM_PICAInPrime EQU $0006BA7C
|
||
ROM_PICAInControl EQU $0006B870
|
||
ROM_PICAInStatus EQU $0006B7B8
|
||
ROM_PICAInClose EQU $0006B7AC
|
||
|
||
ROM_PICAOutOpen EQU $0006B618 ; .Aout
|
||
ROM_PICAOutPrime EQU $0006B9DC
|
||
ROM_PICAOutControl EQU $0006B868
|
||
ROM_PICAOutStatus EQU $0006B7B0
|
||
ROM_PICAOutClose EQU $0006B72C
|
||
|
||
ROM_PICBInOpen EQU $0006B60A ; .BIn
|
||
ROM_PICBInPrime EQU $0006BA82
|
||
ROM_PICBInControl EQU $0006B876
|
||
ROM_PICBInStatus EQU $0006B7BE
|
||
ROM_PICBInClose EQU $0006B7AC
|
||
|
||
ROM_PICBOutOpen EQU $0006B648 ; .BOut
|
||
ROM_PICBOutPrime EQU $0006B9DC
|
||
ROM_PICBOutControl EQU $0006B868
|
||
ROM_PICBOutStatus EQU $0006B7B0
|
||
ROM_PICBoutClose EQU $0006B72C
|
||
|
||
; equates for PIC patches
|
||
IntoChkAConfig EQU $0006AC8A ; for the Open patches
|
||
IntoChkBConfig EQU $0006AC4E
|
||
|
||
ROM_BufferShuffle EQU $0006BD1E ; for the Input Prime patches
|
||
|
||
|
||
backToPICControl EQU $6b898 ; for Control patches
|
||
backToPICKillIO EQU $6b884
|
||
ROM_PICCtlExit EQU $6b8d4
|
||
|
||
backToPICClose EQU $6b764 ; for Close patch
|
||
|
||
StatusErrExit EQU $6b85a ; for Status patch
|
||
BacktoPICStatus EQU $6b7d8
|
||
PICStatusOkExit EQU $6b858
|
||
|
||
;_______________________________________;
|
||
;
|
||
; IOP Driver Headers
|
||
;
|
||
;_______________________________________;
|
||
|
||
DC.b 'wong' ; our personal signature
|
||
PICAsyncAIn
|
||
DC.W $4D00 ; read, control, status, lock
|
||
DC.W 0,0 ; not an ornament
|
||
DC.W 0 ; no menu
|
||
|
||
DC.W PICAInOpen-PICAsyncAIn ; Initialization routine
|
||
DC.W PICAInPrime-PICAsyncAIn ; input Prime routine
|
||
DC.W PICAInControl-PICAsyncAIn ; shared Control routine
|
||
DC.W PICAInStatus-PICAsyncAIn ; shared Status routine
|
||
DC.W PICAInClose-PICAsyncAIn ; Close routine
|
||
|
||
DC.B 4 ; channel A input driver
|
||
DC.B '.AIn '
|
||
|
||
|
||
DC.b 'wong' ; our personal signature
|
||
PICAsyncAOut
|
||
DC.W $4E00 ; write, control, status, lock
|
||
DC.W 0,0 ; not an ornament
|
||
DC.W 0 ; no menu
|
||
|
||
DC.W PICAOutOpen-PICAsyncAOut ; Initialization routine
|
||
DC.W PICAOutPrime-PICAsyncAOut ; output Prime routine
|
||
DC.W PICAOutControl-PICAsyncAOut ; Control routine
|
||
DC.W PICAOutStatus-PICAsyncAOut ; Status routine
|
||
DC.W PICAOutClose-PICAsyncAOut ; Close routine
|
||
|
||
DC.B 5 ; channel A output driver
|
||
DC.B '.AOut'
|
||
|
||
DC.b 'wong' ; our personal signature
|
||
PICAsyncBIn
|
||
DC.W $4D00 ; read, control, status, lock
|
||
DC.W 0,0 ; not an ornament
|
||
DC.W 0 ; no menu
|
||
|
||
DC.W PICBInOpen-PICAsyncBIn ; Initialization routine
|
||
DC.W PICBInPrime-PICAsyncBIn ; input Prime routine
|
||
DC.W PICBInControl-PICAsyncBIn ; Control routine
|
||
DC.W PICBInStatus-PICAsyncBIn ; Status routine
|
||
DC.W PICBInClose-PICAsyncBIn ; Close routine
|
||
|
||
DC.B 4 ; channel B input driver
|
||
DC.B '.BIn '
|
||
|
||
DC.b 'wong' ; our personal signature
|
||
PICAsyncBOut
|
||
DC.W $4E00 ; write, control, status, lock
|
||
DC.W 0,0 ; not an ornament
|
||
DC.W 0 ; no menu
|
||
DC.W PICBOutOpen-PICAsyncBOut ; Initialization routine
|
||
DC.W PICBOutPrime-PICAsyncBOut ; output Prime routine
|
||
DC.W PICBOutControl-PICAsyncBOut ; Control routine
|
||
DC.W PICBOutStatus-PICAsyncBOut ; Status routine
|
||
DC.W PICBOutClose-PICAsyncBOut ; Close routine
|
||
|
||
DC.B 5 ; channel B output driver
|
||
DC.B '.BOut'
|
||
|
||
;_______________________________________;
|
||
;
|
||
; IOP Driver Stubs -- routines that are
|
||
; just along for the ride, and jump back
|
||
; directly to ROM
|
||
;
|
||
;_______________________________________;
|
||
|
||
PICAInClose jmpROM ROM_PICAInClose ; input Close routine
|
||
|
||
;__________________________________
|
||
|
||
PICAOutPrime jmpROM ROM_PICAOutPrime ; output Prime routine
|
||
|
||
;__________________________________
|
||
|
||
PICBInClose jmpROM ROM_PICBInClose ; input Close routine
|
||
|
||
;__________________________________
|
||
|
||
PICBOutPrime jmpROM ROM_PICBoutPrime ; output Prime routine
|
||
|
||
;__________________________________
|
||
;
|
||
; Patched PIC Routines
|
||
;
|
||
;__________________________________
|
||
|
||
; Open Routines
|
||
; We patch out the Open routines because if we jump into ROM Open
|
||
; we'll stuff the ROM PIC driver into the DCE instead of this patched one.
|
||
; So instead we load up the value we want in the DCE ourselves, and
|
||
; then jump into the open patch for the Bypass driver below.
|
||
|
||
; Also note for the Open calls, that because of the way PICChkXXXDrvr
|
||
; is written in ROM, we must the SAME instruction exactly 4 bytes
|
||
; into our Open patch as is in ROM. Else PICChkXXXDrvr would try
|
||
; to jump back to some weird place it wasn't meant to.
|
||
|
||
PICAInOpen jmp @10 ; need 4 bytes here to correspond to ROM driver
|
||
jmpROM ROM_PICAInOpen ; finish up in ROM
|
||
@10 leaROM ROM_AsyncAIn,a2 ; load up the inputs
|
||
lea PICAsyncAIn,a3
|
||
toAOpenPatch leaROM IntoChkAConfig,a0 ; continue on in ChkAConfig
|
||
moveq #4,d1 ; use hyigh 4 bits in SPConfig
|
||
moveq #8,d2 ; and PortAUse
|
||
bra.w OpnFx1 ; go to our byPass driver patch
|
||
|
||
PICAOutOpen jmp @10 ; need 4 bytes here to correspond to ROM driver
|
||
jmpROM ROM_PICAOutOpen ; finish up in ROM
|
||
@10 leaROM ROM_AsyncAOut,a2 ; load up the inputs
|
||
lea PICAsyncAOut,a3
|
||
bra.s toAOpenPatch
|
||
|
||
PICBInOpen jmp @10 ; need 4 bytes here to correspond to ROM driver
|
||
jmpROM ROM_PICBInOpen ; finish up in ROM
|
||
@10 leaROM ROM_AsyncBIn,a2 ; load up the inputs
|
||
lea PICAsyncBIn,a3
|
||
toBOpenPatch leaROM IntoChkBConfig,a0 ; continue on in ChkBConfig
|
||
bra.w OpnFx1
|
||
|
||
PICBOutOpen jmp @10 ; need 4 bytes here to correspond to ROM driver
|
||
jmpROM ROM_PICBOutOpen ; finish up in ROM
|
||
@10 leaROM ROM_AsyncBOut,a2 ; load up the inputs
|
||
lea PICAsyncBOut,a3
|
||
bra.s toBOpenPatch
|
||
;
|
||
; Prime Routines
|
||
;
|
||
; We patch the input prime routines because they're trashing the error code
|
||
; value thru one thread.
|
||
|
||
PICAInPrime move.l SerialVars,d0 ;Port A uses serial vars
|
||
bra.s InPrime
|
||
|
||
PICBInPrime
|
||
move.l ExpandMem,a2 ;Port B uses expand mem
|
||
move.l ExpandMemRec.emSerdVars(a2),d0
|
||
|
||
InPrime
|
||
move.l d0,a2 ;a2 = serial storage ptr (assume ok)
|
||
bgt.s @10 ;output driver is open
|
||
move.w #ReadErr,d0
|
||
move.l JIODone,-(sp) ;output side not open
|
||
rts
|
||
@10
|
||
clr.l ioActCount(a0) ;get ready for read
|
||
move.l a1,10(a2) ;save dce showing cmd active into ReadCmdDCE variable
|
||
|
||
moveq.l #NoErr,d0 ;clear out the error code!!! <41>
|
||
jmpROM ROM_BufferShuffle ;return to the twisted code in ROM
|
||
|
||
;
|
||
; Close Routines
|
||
;
|
||
; So far we only need to patch control for 7.0 VM to unhold the buffer
|
||
; we may have held durning ctl call #9.
|
||
;
|
||
|
||
PICAOutClose
|
||
PICBOutClose
|
||
|
||
with IOPRequestInfo
|
||
|
||
move.l a1,-(sp) ; save dce on stack
|
||
MOVE.L DCtlStorage(A1),a2 ; a2 = handle to local storage
|
||
MOVE.L (A2),A2 ; a2=local storage pointer
|
||
|
||
clr.b PICOpenFlag(a2) ;mark driver as closed
|
||
|
||
;kill the waiters on the event message
|
||
; fixed rmv to use same pb.
|
||
|
||
lea EventMsgPB(a2),a0 ; get address of the waiter
|
||
move.l a0,d0
|
||
_StripAddress ; and strip it
|
||
move.l d0,a0
|
||
move.b #irRemoveRcvWaiter,irRequestKind(a0) ;remove a wait for msg
|
||
_IOPMsgRequest ;remove it
|
||
|
||
;send a close msg to pic
|
||
|
||
move.b #CloseOpCode,OpenMsg+OpCode(a2) ;close opcode
|
||
lea OpenMsgPB(a2),a0 ;send msg to pic
|
||
_IOPMsgRequest
|
||
@10
|
||
tst.b OpenMsgPB+irReqActive(a2) ;is it done yet?
|
||
bne.s @10 ;no, wait some more
|
||
|
||
; and finally do what we came here for...
|
||
jsr UnHoldPICBuf ; unhold the buffer
|
||
jmpROM backToPICClose ; and go back to the ROM
|
||
|
||
endwith
|
||
;
|
||
; UnHoldPICBuf -- unholds the the buffer that may have been held
|
||
; Called by: control, close
|
||
; Inputs: a2 -- ptr to the serial vars
|
||
|
||
UnHoldPICBuf
|
||
; if old buffer was held, we better unhold it. it will have been held
|
||
; if it was not our LocalBuf, i.e. was not in the system heap
|
||
; first time thru this loop InBufPtr is 0.
|
||
move.l #gestaltVMAttr,d0 ; is VM installed?
|
||
_Gestalt
|
||
move.w a0,d0
|
||
beq.s @goodEnd ; if not, we're outta here
|
||
|
||
lea PICLocalBuf(a2),a0 ; inBufPtr = LocalBufPtr?
|
||
move.l a0,d0
|
||
_StripAddress ; being careful
|
||
movea.l PICInBufPtr(a2),a0 ; addr of old buffer
|
||
cmp.l a0,d0
|
||
beq.s @goodEnd ; yes, then don't need to unhold
|
||
cmpa.l #0,a0 ; inBufPtr = 0? (for first time thru)
|
||
beq.s @goodEnd ; yes, then don't need to unhold
|
||
clr.l d0 ; load count.l into a1 <137>
|
||
move.w PICBufSize(a2),d0 ; <137>
|
||
move.l d0,a1 ; <137>
|
||
_UnHoldMemory ; unhold the old buffer
|
||
rts
|
||
|
||
@goodEnd moveq #0,d0 ; everything a-ok
|
||
rts
|
||
;
|
||
; Control Routines
|
||
;
|
||
; So far we only need to patch control for 7.0 VM to hold the buffer in
|
||
; ctl call #9 in memory.
|
||
;
|
||
|
||
PICAOutControl
|
||
PICBOutControl
|
||
move.l DCtlStorage(a1),a2 ;recover handle from DCE
|
||
move.l (a2),a2 ;recover pointer
|
||
bra.s Control_1
|
||
|
||
PICAInControl ;Requires output driver open
|
||
move.l SerialVars,d0 ;Port A uses serial Vars
|
||
bra.s Control
|
||
PICBInControl ;Requires output driver open
|
||
move.l ExpandMem,a2 ;Port B uses expand mem area
|
||
move.l ExpandMemRec.emSerdVars(a2),d0
|
||
|
||
Control
|
||
|
||
;a0 = iopb
|
||
;a1 = dce
|
||
;d0 = address of serial storage (maybe)
|
||
move.l d0,a2 ;a2 = address of serial storage -- assume it is ok
|
||
bgt Control_1 ;is ok if not zero or < 0
|
||
jmpROM backToPICKillIO ;we don't want to be here unless storage ptr is ok
|
||
|
||
Control_1
|
||
move.w CSCode(a0),d1 ;
|
||
cmpi #9,d1 ; opcode 9?
|
||
beq.s Ctl9OpCode ; if so, handle here in the patch
|
||
|
||
jmpROM backToPICControl ; if not, let ROM handle it
|
||
|
||
|
||
;-------------------------------------------------
|
||
; Ctl9OpCode - install/remove user supplied buffers
|
||
; a0 = iopb
|
||
; a1 = dce
|
||
; a2 = output driver local storage
|
||
;-------------------------------------------------
|
||
Ctl9OpCode
|
||
movem.l a0-a1,-(sp) ; save out PB ptr and DCE ptr
|
||
|
||
clr.w PICBufIndex(a2) ;clear input and output indexes
|
||
clr.w PICBufOutdex(a2)
|
||
|
||
move.l CSParam(a0),a4 ; nubuf ptr
|
||
clr.l d1 ; clear out buffer count <135>
|
||
move.w CSParam+4(a0),d1 ;is nubuf being supplied (cnt)
|
||
beq.s @10 ;no, use our own
|
||
|
||
;::::::::::::::::::::::VM STUFF START::::::::::::::::::::::::::
|
||
; hold the new non-local buffer so VM doesn't page it out
|
||
move.l #gestaltVMAttr,d0 ; is VM installed? not on a mac II w/o MMU
|
||
_Gestalt
|
||
move.w a0,d0
|
||
beq.s @15 ; if not, skip the hold
|
||
|
||
movea.l a4,a0 ; hold buffer addr
|
||
movea.l #0,a1 ; clear out count
|
||
movea.l d1,a1 ; hold buffer count <135>
|
||
|
||
; since VM won't let us call _holdmemory with interrupts
|
||
; masked, we return the error that VM spits at us.
|
||
; note that PIC driver does not set interrupt mask at all
|
||
_HoldMemory ; hold the new buffer in memory
|
||
tst.w d0 ; did we get our physical buffer?
|
||
beq.s @15 ; yes, go on
|
||
bra.s toPicCtlExit ; no, punt with a VM error
|
||
@10
|
||
;install our own buffers
|
||
lea PICLocalBuf(a2),a4
|
||
move.w #LclBufSize,d1
|
||
|
||
@15 jsr UnHoldPICBuf ; unhold the old buffer if necessary
|
||
tst.w d0 ; did we release the old buffer?
|
||
bne.s toPicCtlExit ; no, punt with VM error
|
||
;::::::::::::::::::::::VM STUFF STOP:::::::::::::::::::::::::::
|
||
|
||
move.l a4,PICInBufPtr(a2) ; actually install the buffer
|
||
move.w d1,PICBufSize(a2)
|
||
|
||
clr.w d0 ;all done
|
||
|
||
toPicCtlExit movem.l (sp)+,a0-a1 ; restore PB ptr and DCE ptr
|
||
jmpROM ROM_PICCtlExit
|
||
|
||
;
|
||
; Status Routines
|
||
;
|
||
; We patch the status routines in order to provide a new Version number
|
||
; status call (9 and $8000 csCodes). We are adding negative csCodes for
|
||
; system required codes (see David Wong).
|
||
;
|
||
|
||
PICAOutStatus
|
||
PICBOutStatus
|
||
move.l DCtlStorage(a1),a2 ;recover storage ptr from our own DCE
|
||
move.l (a2),a2
|
||
bra.s Status_1
|
||
PICAInStatus
|
||
move.l SerialVars,d0 ;Port A uses serial Vars
|
||
bra.s Status
|
||
PICBInStatus
|
||
move.l ExpandMem,a2 ;Port B uses expand mem area
|
||
move.l ExpandMemRec.emSerdVars(a2),d0
|
||
Status
|
||
;a0 = iopb
|
||
;a1 = dce
|
||
;d0 = address of serial storage (maybe)
|
||
move.l d0,a2 ;a2 = address of serial storage -- assume it is ok
|
||
bne Status_1 ;is ok if not zero or < 0
|
||
move.w #StatusErr,d0 ;mark as status error
|
||
jmpROM StatusErrExit ;error output driver not open
|
||
Status_1
|
||
|
||
|
||
;process the status call always will complete immediately
|
||
;a0 = iopb
|
||
;a1 = dce
|
||
;a2 = output driver storage
|
||
|
||
MOVE.W CSCode(A0),D1 ; get opcode
|
||
cmpi.w #9,d1 ; do we care?
|
||
beq.s @version ; yes
|
||
cmpi.w #$8000,d1 ; largest negative number csCode for Version
|
||
beq.s @version ; yes
|
||
jmpROM BacktoPICStatus
|
||
|
||
@version
|
||
move.b #SerialVers,CSParam(a0); return the version <135>
|
||
jmpROM PICStatusOkExit;
|
||
; end of patched PIC routines
|
||
;_______________________________________
|
||
|
||
;_______________________________________
|
||
;
|
||
; Bypass Patch Code Entry Point
|
||
; (Patched Bypass mode routines here)
|
||
;
|
||
; Called By: we get here via the async serial patch vector ($a0be)
|
||
;
|
||
|
||
SerialPatch
|
||
movem.l d0/a2-a3,-(SP) ; save reg d0,a2,a3 <PMAB401>
|
||
move.l 16(SP),D0 ; get D0 = return address <PMAB401>
|
||
|
||
lea AsyncAIn,a2 ; assume we are coming from AIn
|
||
lea PICAsyncAIn,a3 ;
|
||
cmpRA fromAInOpen,D0 ; test for ChkAConfig call from AInOpen
|
||
beq.w OpenFix
|
||
|
||
lea AsyncAOut,a2 ; assume we are coming from Aout
|
||
lea PICAsyncAOut,a3 ;
|
||
cmpRA fromAOutOpen,D0 ; test for ChkAConfig call from AOutOpen
|
||
beq.w OpenFix
|
||
|
||
lea AsyncBIn,a2 ; assume we are coming from BIn
|
||
lea PICAsyncBIn,a3 ;
|
||
cmpRA fromBInOpen,D0 ; test for ChkBConfig call from BBInOpen
|
||
beq.w OpenFix
|
||
|
||
lea AsyncBOut,a2 ; assume we are coming from Bout
|
||
lea PICAsyncBOut,a3 ;
|
||
cmpRA fromBOutOpen,D0 ; test for ChkBConfig call from BOutOpen
|
||
beq.w OpenFix
|
||
|
||
move.l 12(sp),d0 ; one less level indirection for non-open calls
|
||
|
||
cmpRA fromControl,d0 ; to fix bypass control calls
|
||
beq.w ControlFix
|
||
|
||
cmpRA fromStatus,d0 ; to fix bypass control calls
|
||
beq.w StatusFix
|
||
|
||
cmpRA fromClose,d0 ; to fix bypass close calls
|
||
beq.w CloseFix
|
||
|
||
cmpRA fromInitSCC,d0 ; to fix initSCC routine
|
||
beq.w InitSCCFix
|
||
|
||
movem.l (sp)+,d0/a2-a3 ; restore regs <PMAB401>
|
||
RTS ; back to ROM
|
||
|
||
;
|
||
; Close fixes-- so far we only need to do it for 7.0 VM to unhold
|
||
; the buffer we may have held in control call #9.
|
||
;
|
||
CloseFix
|
||
ADD.L #16,SP ; pop save reg d0, for some reason the driver saved
|
||
; out ptr to globals in a6
|
||
move.l a1,-(sp) ; save out the DCE ptr
|
||
MOVE.L (A6),A2 ; get locals pointer <14Oct85>
|
||
TST.B CtlOptions(A2) ; leave DTR unchanged? <14Oct85>
|
||
bmi.s @1 ; <C216/16oct86>
|
||
bclr #7,XmitBits(A2) ; no, clear the DTR bit <C216/16oct86>
|
||
bclr #7,WR5AVal(A2) ; <C216/16oct86>
|
||
@1 bclr #3,XmitBits(A2) ; always clear Tx enable <C216/16oct86>
|
||
|
||
jsrROM SyncOutput ; delay until last char has cleared <14Oct85>
|
||
; output buffer
|
||
LeaROM ResetData,A3
|
||
MOVEQ #ResetLth,D1
|
||
jsrROM InitSCC1 ; shut down the channel
|
||
|
||
; now that we've shut down the channel it should be safe to unhold
|
||
; the input buffer. we won't check for error since we can't do much
|
||
; about it anyway.
|
||
jsr UnHoldInputBuf ; unhold the buffer if necessary
|
||
move.l (sp)+, a1 ; restore the DCE ptr
|
||
jmpROM backToClose
|
||
|
||
;::::::::::::::::::::::VM STUFF START::::::::::::::::::::::::::
|
||
;
|
||
; UnHoldInputBuf -- unholds the the buffer that may have been held
|
||
; Called by: control, close
|
||
; Inputs: a2 -- ptr to the serial vars
|
||
|
||
; if old buffer was held, we better unhold it. it will have been held
|
||
; if it was not our LocalBuf, i.e. was not in the system heap
|
||
; first time thru this loop InBufPtr is 0.
|
||
UnHoldInputBuf
|
||
move.l #gestaltVMAttr,d0 ; is VM installed?
|
||
_Gestalt
|
||
move.w a0,d0
|
||
beq.s @goodEnd ; if not, we're outta here
|
||
|
||
; check usual case...is inBufPtr equal to LocalBufPtr?
|
||
move.l d1,-(sp) ; save a reg
|
||
lea LocalBuf(a2),a0 ;inBufPtr = LocalBufPtr?
|
||
move.l a0,d1
|
||
move.l InBufPtr(a2),d0
|
||
eor.l d1,d0
|
||
_StripAddress ; ignore differences in the high bits
|
||
move.l (sp)+,d1 ; restore a reg
|
||
tst.l d0 ;
|
||
beq.s @goodEnd ; same, so don't need to unhold
|
||
|
||
; check first time thru case, when InBufPtr
|
||
; would equal zero
|
||
move.l InBufPtr(a2),d0 ; for first time thru, is InBufPtr zero?
|
||
beq.s @goodEnd ; yes, then don't need to unhold
|
||
|
||
; unhold the puppy
|
||
movea.l d0,a0 ; a0 <- ptr
|
||
moveq #0,d0 ; clear out count
|
||
move.w BufSize(a2),d0 ;
|
||
movea.l d0,a1 ; a1<- cnt
|
||
_UnHoldMemory ; unhold the old buffer
|
||
rts
|
||
|
||
@goodEnd moveq #0,d0 ; everything a-ok
|
||
rts
|
||
|
||
;::::::::::::::::::::::VM STUFF STOP:::::::::::::::::::::::::::
|
||
|
||
;
|
||
; Routine: InitSCC
|
||
; Patch: --We patch this routine to use the InitData table here in RAM
|
||
; instead of the one in ROM. We do this so that the values in
|
||
; WR11 and WR14 aren't hardcoded, so that we can support external
|
||
; clocking.
|
||
; --We also fix the value of StopBits (WR4) here to have the clock
|
||
; divide bits correspond to the the external/internal clock state
|
||
; indicated in CtlOptions. We do this here so that CtlConfig calls
|
||
; won't stomp StopBits in the ToSCCInit routine.
|
||
; --We also disable HWHS so we don't try to use CTS line for both
|
||
; clocking and handshaking.
|
||
clkBit equ 6 ; bit 6 in CtlOptions controls ext/int SCC clk
|
||
clkDvdBit equ 6 ; divide clock bit in WR4
|
||
clkMask equ %01000000 ; mask for getting at clkBit <129>
|
||
extClkSrc equ %00101000 ; SCC clk src is TRxC (CTS) pin (WR11) <129>
|
||
intClkSrc equ %01010000 ; SCC clk src is baud rate generator (WR11) <129>
|
||
BRGEnbl equ %00000001 ; enable baud rate generator (WR14) <129>
|
||
BRGDsbl equ %00000000 ; disable baud rate generator (WR14) <129>
|
||
|
||
SCCDataTable
|
||
DC.B $02,9 ; status in low bits, MIE disabled
|
||
clkDvd DC.B 4,$FF ; x16 clk, stop bits, parity options
|
||
DC.B 1,$FF ; WR1 reg, first write
|
||
DC.B 3,$FF ; bits/char option rcvr
|
||
DC.B 5,$FF ; bits/char option xmitter
|
||
DC.B $00,2 ; zero interrupt vector
|
||
DC.B $00,10 ; NRZ encoding
|
||
ClkMode DC.B $50,11 ; brgen/TRxC clk to rcvr, xmitter--default to internal
|
||
DC.B 12,$FF ; set baud rate low byte
|
||
DC.B 13,$FF ; set baud rate high byte
|
||
|
||
DC.B 3,$FF ; enable rcvr
|
||
DC.B 5,$FF ; enable xmitter
|
||
BRGEnable DC.B $01,14 ; enb/disable baud rate generator from RTxC pin --default to on
|
||
dc.b $A0,15 ; Break, CTS external ints (dcd not needed) <2.3>
|
||
DC.B $10,0 ; reset ext/status twice
|
||
DC.B $10,0
|
||
DC.B 1,$FF ; w/req pin configuration
|
||
DC.B $0A,9 ; enable interrupts, status in low bits
|
||
|
||
SCCDataTableLth EQU *-SCCDataTable ;
|
||
|
||
InitSCCFix
|
||
movem.l (sp)+,d0/a2-a3 ; restore drvr storage ptr in a2, InitSCC table in a3
|
||
add.l #4,sp ; pop saved rtrn addr--we jump back
|
||
|
||
move.l a3,d0
|
||
cmpRA InitData,d0 ; are we initializing SCC?
|
||
bne @done
|
||
|
||
lea SCCDataTable,a3 ; use our RAM table instead of the ROM one
|
||
moveq #SCCDataTableLth,d1
|
||
|
||
movem.l d1/a0,-(sp) ; save out reg's <129>
|
||
|
||
; default to internally clocked state <129>
|
||
bset.b #clkDvdBit,StopBits(a2) ; default to a divide-by-16 clock <129>
|
||
moveq #intClkSrc,d0 ; internal clocking source <129>
|
||
moveq #BRGEnbl,d1 ; enable baud rate generator <129>
|
||
|
||
btst.b #clkBit,CtlOptions(a2) ; are we externally clocked?
|
||
beq.s @load ; not externally clocked, so load
|
||
|
||
; set to externally clocked state
|
||
bclr.b #clkDvdBit,StopBits(a2) ; set to a divide-by-one clock <129>
|
||
moveq #extClkSrc,d0 ; external clock source <129>
|
||
moveq #BRGDsbl,d1 ; disable baud rate generator <129>
|
||
clr.b HWHS(a2) ; make sure we're not trying to do HWHS <129>
|
||
|
||
@load lea ClkMode,a0 ; load params into InitSCC data table <129>
|
||
move.b d0,(a0) ; <129>
|
||
lea BRGEnable,a0 ; <129>
|
||
move.b d1,(a0) ; <129>
|
||
|
||
movem.l (sp)+,d1/a0 ; restore reg's <129>
|
||
@done jmpROM backToInitSCC ; finish up in ROM
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
;
|
||
; Routine: Status
|
||
; Patch: We patch status to add a call to return the driver's version.
|
||
StatusFix
|
||
movem.l (sp)+,d0/a2-a3 ; restore drvr storage ptr in a2
|
||
add.l #4,sp ; pop saved rtrn addr--we jump back
|
||
|
||
MOVE.W IOTrap(A0),-(SP) ; save trap to distinguish immed calls<14Oct85>
|
||
MOVE.L A1,-(SP) ; save passed DCE for in/out <14Oct85>
|
||
MOVE.W SR,-(SP) ; disable interrupts for ctl call <14Oct85>
|
||
ORI #HiIntMask,SR ; <A357/06nov86>
|
||
LEA CSCode(A0),A0 ; get pointer to return parameters
|
||
MOVEQ #StatusErr,D0 ; assume status error
|
||
MOVE.L A2,D1 ; have our variables been set up? <14Oct85>
|
||
Bgt @stat1 ; exit if not (only input side open)
|
||
jmpROM ROM_CtlExit ; just like ROM
|
||
|
||
@stat1 MOVE.W (A0)+,D1 ; get opcode
|
||
|
||
cmpi.w #9,d1 ; do we care?
|
||
beq.s @version ; yes
|
||
cmpi.w #$8000,d1 ; largest negative number csCode for Version
|
||
beq.s @version ; yes
|
||
jmpROM BackToStatus ; no
|
||
|
||
@version move.b #SerialVers,(a0) ; return the version <135>
|
||
jmpROM ROM_CtlGood
|
||
|
||
;
|
||
; Routine: Control
|
||
; Patch: We patch control for the following reasons:
|
||
; 1) to add VM support for control call 9--lock/unlock the buffer
|
||
; 2) to add external clock support in control call 16
|
||
;
|
||
ControlFix
|
||
movem.l (sp)+,d0/a2-a3 ; restore drvr storage ptr in a2
|
||
add.l #4,sp ; pop saved rtrn addr--we jump back
|
||
|
||
MOVE.W IOTrap(A0),-(SP) ; save trap to distinguish immed calls<14Oct85>
|
||
MOVE.L A1,-(SP) ; save passed DCE for in/out <14Oct85>
|
||
MOVE.W SR,-(SP) ; disable interrupts for ctl call <14Oct85>
|
||
ORI #HiIntMask,SR ; <A357/06nov86>
|
||
|
||
moveq #0,d0 ; for the killIO call
|
||
LEA CSCode(A0),A0 ; get parameters
|
||
MOVE.W (A0)+,D1 ; get opcode
|
||
|
||
cmpi.w #9,d1 ; opcode 9? (buffer)
|
||
beq CtlBuffer ; if so, handle here in the patch
|
||
cmpi.w #16,d1 ; opcode 16? (ctlOptions) <extClk>
|
||
beq CtlSwitchCTSClock ; <extClk>
|
||
jmpROM backToControl ; if not, let ROM handle it
|
||
|
||
|
||
|
||
;_______________________________________;
|
||
;
|
||
; Install a new input buffer.
|
||
;
|
||
; The patch is needed for 7.0 VM. We must 'hold' the buffer in memory
|
||
; so that there is no possibility it is paged out at interrupt time (which
|
||
; would have the potential for causing a double page fault).
|
||
;_______________________________________;
|
||
|
||
CtlBuffer CLR.L BufIndex(A2) ; clear in and out indices
|
||
|
||
MOVE.L (A0)+,A4 ; buffer pointer
|
||
moveq #0,d1 ; clear out length reg
|
||
MOVE.W (A0),D1 ; length of buffer?
|
||
BEQ.S InstllLBuf ; if zero, revert to our own buffer
|
||
|
||
; hold the new non-local buffer so VM doesn't page it out
|
||
move.l #gestaltVMAttr,d0 ; is VM installed? not on a mac II w/o MMU
|
||
_Gestalt
|
||
move.w a0,d0
|
||
beq.s InstllABuf ; if not, skip the hold
|
||
|
||
movea.l a4,a0 ; hold buffer addr
|
||
movea.l d1,a1 ; hold buffer count
|
||
; since VM won't let us call _holdmemory with interrupts
|
||
; masked, we set the interrupt level back to that app's
|
||
; interrupt level, which hopefully was zero. If so, then
|
||
; everything should be peachy. If not, then we return the
|
||
; error that VM spits at us.
|
||
move.w sr,-(sp) ; save our int lvl
|
||
move.w 2(sp),d0 ; get app's int lvl
|
||
and.w (sp),d0 ; and set us to that
|
||
move.w d0,sr
|
||
|
||
_HoldMemory ; hold the new buffer in memory
|
||
move.w (sp)+,sr ; and restore our int lvl
|
||
|
||
tst.w d0 ; did we get our physical buffer?
|
||
beq.s InstllABuf ; yes, go on
|
||
Ctl_Err jmpROM ROM_CtlExit ; no, then pass back VM error
|
||
|
||
; InstllLBuf is also called from OpenInstall!
|
||
|
||
InstllLBuf LEA LocalBuf(A2),A4 ; use our meager local buffer for now
|
||
MOVEQ #LclBufSize,D1 ;
|
||
|
||
InstllABuf
|
||
; since VM won't let us call _holdmemory with interrupts
|
||
; masked, we set the interrupt level back to that app's
|
||
; interrupt level, which hopefully was zero. If so, then
|
||
; everything should be peachy. If not, then we return the
|
||
; error that VM spits at us.
|
||
move.w sr,-(sp) ; save our int lvl
|
||
move.w 2(sp),d0 ; get app's int lvl
|
||
and.w (sp),d0 ; and set us to that
|
||
move.w d0,sr
|
||
|
||
jsr UnHoldInputBuf ; unhold the buffer if necessary
|
||
|
||
move.w (sp)+,sr ; restore our int lvl
|
||
tst.w d0 ; did we release old buffer?
|
||
bne.s Ctl_Err ; no, pass back VM error
|
||
|
||
jsrROM FinishCall9 ; and finish up the call in ROM
|
||
jmpROM ROM_CtlGood ; and go back to ctl call dispatcher
|
||
;::::::::::::::::::::::VM STUFF STOP:::::::::::::::::::::::::::
|
||
|
||
|
||
; Routine: SetCtlOptions -- Opcode 16
|
||
; Patch: We patch this routine so that bit 6 of CtlOptions variable now
|
||
; controls a switch to internal/external clocking on the CTS (HSIn) line.
|
||
; We must call InitSCC to get the clocking option to kick in.
|
||
; Inputs: byte number in IOPB value
|
||
; (26) [$0010] opcode
|
||
; (28) bit 7 = 0 for drop DTR at close
|
||
; bit 7 = 1 for leave DTR unchanged at close
|
||
; bit 6 = 0 for internal clocking
|
||
; bit 6 = 1 for external clocking
|
||
; bits 0-5 reserved for future use
|
||
; Notes: We will not put control for the GPI internal/external
|
||
; clocking switch here, as that requires the control of
|
||
; HW external to the SCC (namely, the VIA vSync pin). Control
|
||
; of the GPIa line is in _HWPriv.
|
||
;
|
||
|
||
CtlSwitchCTSClock
|
||
move.b (a0),CtlOptions(a2) ; store new value <129>
|
||
jsrROM InitSCC ; set up the SCC according to new value <129>
|
||
jmpROM ROM_CtlGood ; finish up in ROM <129>
|
||
|
||
|
||
;
|
||
; Open Fixes
|
||
;
|
||
;
|
||
; note that no stack fiddling is allowed, as the chkConfigure EXPECTS to be called directly
|
||
; from the open routine, and will not go to IOCore with error properly should one occur.
|
||
|
||
; Common code for open patches
|
||
|
||
OpenFix move.l d0,a4 ; save where we came from w/o use of the stack
|
||
ADD.L #12,SP ; pop save reg d0,a2,a3 - not needed <PMAB401>
|
||
MOVE.L (SP)+,A0 ; pop A0 = addr to continue ChkConfig
|
||
addq #4,SP ; pop async open ret addr - will jmp back
|
||
OpnFx1 jsr (a0) ; finish ChkConfig (A1,D1,D2 params)
|
||
|
||
|
||
; check to see whether we are in IOP or Bypass mode
|
||
if isUniversal then ; <2.1>
|
||
TestFor SCCIOPExists ;check to see if we even have an IOP <2.1>
|
||
beq.s @05 ;if not, just use bypass mode driver <2.1>
|
||
endif ; <2.1>
|
||
|
||
btst #0,SCCIOPFlag ;are we in bypass mode? <8.7> test low mem, not PRAM
|
||
bne.s @05 ;yes, in bypass mode; use SCC driver <8.7> change bit sense
|
||
|
||
move.l a3,a2 ; plug in PIC driver header address
|
||
@goback jmpROM PlugInDrvr ; go finish open call
|
||
|
||
|
||
; install our RAM-based bypass driver header into DCE <125>
|
||
; a2 has pointer to RAM driver header
|
||
; a1 has pointer to DCE
|
||
@05
|
||
move.l a2,(a1) ; install ourselves into the DCE
|
||
|
||
; check again where we came from to see if which open fix to branch off to.
|
||
move.l a4,d0 ; restore where we came from
|
||
cmpRA fromAOutOpen,d0 ; test for ChkAConfig call from AOutOpen
|
||
beq.s FixAout
|
||
|
||
cmpRA fromBOutOpen,d0 ; test for ChkAConfig call from AOutOpen
|
||
beq.s FixBout
|
||
|
||
jmpROM backToInOpen ; for In driver just go finish open call <125>
|
||
|
||
FixAout
|
||
; replace receive routine vectors installed by async open
|
||
LEA PortAVars,A2 ; local variables address
|
||
peaROM ROM_PollDtaIn,-(sp) ; ROM--this proc handles disk poll data <20Oct85>
|
||
pea NewSCAIntHnd ; Special RxD int handler <4> <20Oct85>
|
||
pea NewRAIntHnd ; int handler <4> <20Oct85>
|
||
peaROM ROM_TAIntHnd,-(sp) ; ROM--TxD int handler <20Oct85>
|
||
PEA Lvl2DT+16 ; SCC interrupt dispatch table, chan A <20Oct85>
|
||
PEA NewExtAIntHnd ; External int handler <20Oct85>
|
||
jmpROM backToAOutOpen ; JUMP BACK INTO ROM
|
||
|
||
FixBout
|
||
; replace receive routine vectors installed by async open
|
||
move.l ExpandMem,a2 ; local variable address in is <2.0>
|
||
lea ExpandMemRec.emSerdVars(a2),a2 ; expandmem <2.0>
|
||
CLR.L -(SP) ; no disk poll routine
|
||
pea NewSCBIntHnd ; Special RxD int handler <4> <20Oct85>
|
||
pea NewRBIntHnd ; RxD int handler <4> <20Oct85>
|
||
peaROM ROM_TBIntHnd,-(sp) ; ROM--TxD int handler <20Oct85>
|
||
PEA Lvl2DT ; SCC interrupt dispatch table, chan B <20Oct85>
|
||
PEA NewExtBIntHnd ; External int handler <20Oct85>
|
||
jmpROM backToBOutOpen ; JUMP BACK INTO ROM
|
||
|
||
|
||
;-----------------------------------------------------------------------
|
||
;
|
||
; Interrupt Handlers
|
||
;
|
||
;-----------------------------------------------------------------------
|
||
;________________________________________________________________________
|
||
;
|
||
; Routine: RXIntHnd
|
||
;
|
||
; Arguments: A0 (input) -- chan A/B control read address
|
||
; A1 (input) -- chan A/B control write address
|
||
;
|
||
; Function: This routine handles SCC receiver interrupts for
|
||
; both channels; the data is read and stashed, IODone called
|
||
; if necessary.
|
||
;
|
||
; Patches: Patched to fix the serial thruput problem on Apollo and TimLC. <4>
|
||
; If we complete a device manager request we change the return
|
||
; address on the stack to return to the primary
|
||
; level 4 interrupt dispatcher, rather than to the code in the
|
||
; secondary dispatcher that checks to see if there is another
|
||
; RxChar available (and loops to process the next interrupt if so).
|
||
; This way we guarantee that we return all the way out of the interrupt
|
||
; handlers at least once per device manager request, allowing
|
||
; things like deferred tasks a chance to run.
|
||
;________________________________________________________________________
|
||
|
||
Lvl4IntPatchSize equ 10 ; size of interrupt patch code
|
||
|
||
NewRBIntHnd
|
||
move.l ExpandMem,a3 ; get appropriate variables (chan B) <2.0>
|
||
lea ExpandMemRec.emSerdVars(a3),a3 ; <2.0>
|
||
|
||
BRA.S RXIntHnd ; go to shared code
|
||
|
||
NewRAIntHnd LEA PortAVars,A3 ; get appropriate variables (chan A)
|
||
|
||
RXIntHnd MOVE.B SCCData(A0),D0 ; get the data byte
|
||
|
||
PollStash MOVE.L (A3)+,A2 ; get pointer to local variables
|
||
move.l InDCE(a2),a3 ; and DCE pointer <2.0>
|
||
|
||
AND.B CharMask(A2),D0 ; zero unused high bits <14Oct85>
|
||
|
||
MOVE.B PEChar(A2),D1 ; Are we translating PE Characters?
|
||
BEQ.S @1 ; No, just save the char.
|
||
CMP.B D1,D0 ; Is the new char a PEChar?
|
||
BNE.S @1 ; No, just do normal stuff
|
||
MOVE.B AltChar(A2),D0 ; Make sure that a good char <14Oct85>
|
||
; doesn't look like PEChar.
|
||
@1 TST.B SWHS(A2) ; software handshake enabled?
|
||
BEQ.S StashIt ; branch if not
|
||
CMP.B XONChar(A2),D0 ; was this an XON? <14Oct85>
|
||
bne.s chkXoff ; not an XOn <4>
|
||
ContOut CLR.B XOFFlag(A2) ; we got an XON, so clear Xoff-received flag <4>
|
||
jmpROM ToContOut1 ; XOn, so start output again <4>
|
||
|
||
chkXoff CMP.B XOFFChar(A2),D0 ; how about an XOFF? <14Oct85><4>
|
||
BNE.S StashIt ; if not, then stash the character
|
||
ST XOFFlag(A2) ; if so, then note it
|
||
InputRTS rts ; and exit <4>
|
||
|
||
; stash byte in the user's buffer if a request is pending, otherwise use our own
|
||
|
||
StashIt TST.B ReadCmd(A2) ; read request pending?
|
||
bne.s PutInUserBuf ; request pending, so stash byte in user buffer <4>
|
||
jmpROM ROM_PutInOurBuf ; no request pending, so stash byte in our buffer <4>
|
||
|
||
PutInUserBuf
|
||
MOVE.L A3,A1 ; get DCE pointer
|
||
jsrROM ROM_toStash ; use utility routine to save code <4>
|
||
BPL.S InputRTS ; if request isn't finished, just RTS
|
||
CLR.B ReadCmd(A2) ; no longer a read request pending
|
||
add.l #Lvl4IntPatchSize,(sp); return to rts at end of int dispatcher <patch><4>
|
||
; so we return out of Interrupt handler completely
|
||
; since we have finished a request
|
||
jmpROM ROM_GoodFinish ; we have a good finish
|
||
|
||
;________________________________________________________________________
|
||
;
|
||
; Routine: SCIntHnd
|
||
;
|
||
; Arguments: A0 (input) -- channel A/B control read address
|
||
; A1 (input) -- channel A/B control write address
|
||
;
|
||
; Function: This routine handles SCC special condition interrupts:
|
||
; these occur when an input character is received that has
|
||
; a parity error, framing error, or causes an overrun.
|
||
; If the option is set to abort on the error, the character
|
||
; is discarded and the input request (if any) aborted; otherwise,
|
||
; the error is noted and the character buffered as usual.
|
||
;
|
||
; Patch: Must patch this rtn because we patch the RxIntHnd which <4>
|
||
; includes the 'Stashit' label called here.
|
||
;
|
||
; If there are no special condition bits set, then this is NOT <5>
|
||
; a special-condition interrupt, but an interrupt for which
|
||
; the cause has already been removed. This occured with the
|
||
; Stylewriter on faster machines, when we wrote out a byte
|
||
; faster than the TBE interrupt could be generated (after
|
||
; the TBE bit was set in RR0).
|
||
;________________________________________________________________________
|
||
|
||
NewSCBIntHnd
|
||
move.l ExpandMem,a3 ; get appropriate variables (chan B) <2.0>
|
||
lea ExpandMemRec.emSerdVars(a3),a3 ; <2.0>
|
||
BRA.S SCIntHnd ; go to shared code
|
||
|
||
NewSCAIntHnd LEA PortAVars,A3 ; get appropriate variables (chan A)
|
||
|
||
SCIntHnd MOVE.B #1,(A1) ; point to error reg
|
||
MOVE.L (A3)+,A2 ; get local variables pointer
|
||
move.l InDCE(a2),A3 ; and DCE pointer (delay, too) <2.0>
|
||
|
||
MOVE.B (A0),D1 ; read the error condition
|
||
|
||
MOVEQ #$70,D3 ; form $70 mask
|
||
AND.B D3,D1 ; isolate error bits
|
||
beq.s InputRTS ; no errors posted, then this is not a SC interrupt <5>
|
||
OR.B D1,AsyncErr(A2) ; accumulate errors (delay, too)
|
||
MOVE.B SCCData(A0),D0 ; get the data byte
|
||
AND.B CharMask(A2),D0 ; zero unused high-order bits <14Oct85>
|
||
|
||
MOVE.B Options(A2),D2 ; get abort options
|
||
AND.B D1,D2 ; should we abort?
|
||
MOVE.B #$30,(A1) ; reset the error flag
|
||
AND.B D3,D2
|
||
beq.s @dontAbort ; options say we should NOT abort request <4>
|
||
jmpROM ROM_abortReq ; options say we should abort request <4>
|
||
|
||
@dontAbort MOVE.B PEChar(A2),D3 ; alternate char for parity errors? <4>
|
||
BEQ.S @1 ; br if not
|
||
CMP.B D0,D3 ; Is the incoming char equal to the PEChar?
|
||
BNE.S @0 ; No, no substitution needed.
|
||
MOVE.B AltChar(A2),D0 ; Make sure that a good char <14Oct85>
|
||
; doesn't look like PEChar.
|
||
@0 BTST #4,D1 ; parity error?
|
||
BEQ.S @1 ; br if not
|
||
MOVE.B D3,D0 ; replace it
|
||
|
||
@1 bra.s StashIt ; go stash it . . .<StashIt is IN RAM NOW> <4>
|
||
|
||
;________________________________________________________________________
|
||
;
|
||
; Routine: ExtIntHnd
|
||
;
|
||
; Arguments: A0 (input) -- channel A/B control read address
|
||
; A1 (input) -- channel A/B control write address
|
||
; D0 (input) -- SCC read reg 0 value
|
||
; D1 (input) -- SCC read reg 0 changed bits
|
||
;
|
||
; Function: This routine handles SCC external/status interrupts for
|
||
; both channels; mouse (DCD) interrupts are passed along to the
|
||
; mouse interrupt handler in CrsrCore. Only Break/Abort and CTS
|
||
; external interrupts are enabled (besides DCD).
|
||
;
|
||
; Note that CTS low in read reg 0 currently means that the
|
||
; hardware handshake line is asserted which means 'ok to transmit'.
|
||
;________________________________________________________________________
|
||
|
||
|
||
NewExtBIntHnd
|
||
move.l ExpandMem,a3 ; get appropriate variables - chan B <2.0>
|
||
move.l ExpandMemRec.emSerdVars(a3),a2 ; <2.0>
|
||
move.w #28,d2 ; .Bin is offset 28 into unit table <126>
|
||
bra.s ExtIntHnd
|
||
|
||
NewExtAIntHnd
|
||
LEA PortAVars,A3 ; get appropriate variables - chan A
|
||
MOVE.L (A3)+,A2 ; get pointer to local variables
|
||
move.w #20,d2 ; Ain is offset 20 in the unit table <126>
|
||
|
||
ExtIntHnd
|
||
movea.l UTableBase,a3 ; get addr of Utable <126>
|
||
movea.l 0(a3,d2.w),a3 ; get DCE handle (d2 has offset) <126>
|
||
movea.l (a3),a3 ; get DCE ptr <126>
|
||
|
||
MOVE.B D1,D2 ; changed bits
|
||
AND.B postOptions(A2),D2 ; post this change?
|
||
BEQ.S @0 ; br if not
|
||
|
||
MOVEM.L D0/A0,-(SP) ; preserve these registers
|
||
MOVE.W #IODrvrEvt,A0
|
||
ASL.W #8,D0 ; make room for 'changed' values
|
||
MOVE.B D1,D0
|
||
SWAP D0 ; make room for driver refnum
|
||
MOVE.W DCtlRefnum(A3),D0
|
||
|
||
_PostEvent ; and post the event
|
||
MOVEM.L (SP)+,D0/A0
|
||
|
||
@0 TST.B D1 ; see if it's a change in break status
|
||
BMI.S extBreak ; branch if it was a break interrupt
|
||
LSL.B #2,D0 ; must be CTS change
|
||
|
||
SMI CTSFlag(A2) ; set flags according to CTS
|
||
|
||
; This piece of code is used to detect a clock into the HWHS line
|
||
; and shut off the ext/sts interrupt for the handshake line.
|
||
|
||
CMP.W #80,HSCount(A2) ; exceeded 80 transitions in 16 MS? <14Oct85>
|
||
BCS.S @2 ; br if not <14Oct85>
|
||
|
||
MOVEQ #-128,D0 ; ($80) leave break ints enabled <14Oct85>
|
||
MOVEQ #15,D1 ; write register 15 <14Oct85>
|
||
jsrROM ToCtlSet ; <patch>
|
||
|
||
|
||
@2 MOVE.L Ticks,D2 ; get current tick time <14Oct85>
|
||
CMP.L LastTime(A2),D2 ; same as last? <14Oct85>
|
||
BEQ.S @3 ; br if so <14Oct85>
|
||
MOVE.L D2,LastTime(A2) ; new last time <14Oct85>
|
||
CLR.W HSCount(A2) ; restart count for new time <14Oct85>
|
||
|
||
@3 ADDQ #1,HSCount(A2) ; update count <14Oct85>
|
||
jmpROM toContOut1 ;<patch> BRA ContOut1--if freshly asserted, continue output<14Oct85>
|
||
|
||
extBreak TST.B D0 ; check break level
|
||
BMI.S @1 ; if it's asserted, terminate any input
|
||
MOVE.B SCCData(A0),D0 ; otherwise (end of break), discard null
|
||
@0 RTS ; and return
|
||
|
||
@1 MOVEQ #BreakRecd,D0 ; note the break
|
||
bset.b #3,AsyncErr(a2) ; we now note break level in status
|
||
TST.B ReadCmd(A2) ; read request pending?
|
||
beq.s @0 ; just return if done <7.1>
|
||
|
||
jmpROM ToRdReqDone ; return to ROM code
|
||
|
||
;_______________________________________________________________________
|
||
;
|
||
; Patched Driver headers (with signature long word before each header)
|
||
;
|
||
DC.b 'wong' ; our personal signature
|
||
AsyncAIn
|
||
DC.W $4D00 ; read, control, status, lock
|
||
DC.W 0,0 ; not an ornament
|
||
DC.W 0 ; no menu
|
||
|
||
DC.W AInOpen-AsyncAIn ; Initialization routine
|
||
DC.W AInPrime-AsyncAIn ; input Prime routine
|
||
DC.W AControl-AsyncAIn ; shared Control routine
|
||
DC.W AStatus-AsyncAIn ; shared Status routine
|
||
DC.W AInClose-AsyncAIn ; Close routine
|
||
|
||
DC.B 4 ; channel A input driver
|
||
DC.B '.AIn '
|
||
|
||
|
||
DC.b 'wong' ; our personal signature
|
||
AsyncAOut
|
||
DC.W $4E00 ; write, control, status, lock
|
||
DC.W 0,0 ; not an ornament
|
||
DC.W 0 ; no menu
|
||
|
||
DC.W AOutOpen-AsyncAOut ; Initialization routine
|
||
DC.W AOutPrime-AsyncAOut ; output Prime routine
|
||
DC.W AControl-AsyncAOut ; shared Control routine
|
||
DC.W AStatus-AsyncAOut ; shared Status routine
|
||
DC.W AOutClose-AsyncAOut ; Close routine
|
||
|
||
DC.B 5 ; channel A output driver
|
||
DC.B '.AOut'
|
||
|
||
DC.b 'wong' ; our personal signature
|
||
AsyncBIn
|
||
DC.W $4D00 ; read, control, status, lock
|
||
DC.W 0,0 ; not an ornament
|
||
DC.W 0 ; no menu
|
||
|
||
DC.W BInOpen-AsyncBIn ; Initialization routine
|
||
DC.W BInPrime-AsyncBIn ; input Prime routine
|
||
DC.W BControl-AsyncBIn ; shared Control routine
|
||
DC.W BStatus-AsyncBIn ; shared Status routine
|
||
DC.W BInClose-AsyncBIn ; Close routine
|
||
|
||
DC.B 4 ; channel B input driver
|
||
DC.B '.BIn '
|
||
|
||
DC.b 'wong' ; our personal signature
|
||
AsyncBOut
|
||
DC.W $4E00 ; write, control, status, lock
|
||
DC.W 0,0 ; not an ornament
|
||
DC.W 0 ; no menu
|
||
DC.W BOutOpen-AsyncBOut ; Initialization routine
|
||
DC.W BOutPrime-AsyncBOut ; output Prime routine
|
||
DC.W BControl-AsyncBOut ; shared Control routine
|
||
DC.W BStatus-AsyncBOut ; shared Status routine
|
||
DC.W BOutClose-AsyncBOut ; Close routine
|
||
|
||
DC.B 5 ; channel B output driver
|
||
DC.B '.BOut'
|
||
|
||
;_______________________________________________________________________
|
||
;
|
||
; jumping to ROM from our patched entry points
|
||
;
|
||
AInOpen jmpROM ROM_AInEntryOpen ;port a <125>
|
||
AInClose jmpROM ROM_AInEntryClose
|
||
AInPrime jmpROM ROM_AInEntryPrime
|
||
|
||
AOutOpen jmpROM ROM_AOutEntryOpen
|
||
AOutClose jmpROM ROM_AOutEntryClose
|
||
AOutPrime jmpROM ROM_AOutEntryPrime
|
||
|
||
AControl jmpROM ROM_AEntryControl
|
||
AStatus jmpROM ROM_AEntryStatus
|
||
|
||
BInOpen jmpROM ROM_BInEntryOpen ;port b
|
||
BInClose jmpROM ROM_BInEntryClose
|
||
BInPrime jmpROM ROM_BInEntryPrime
|
||
|
||
BOutOpen jmpROM ROM_BOutEntryOpen
|
||
BOutClose jmpROM ROM_BOutEntryClose
|
||
BOutPrime jmpROM ROM_BOutEntryPrime
|
||
|
||
BControl jmpROM ROM_BEntryControl
|
||
BStatus jmpROM ROM_BEntryStatus
|
||
|
||
endproc
|
||
;_______________________________________________________________________
|
||
; <7.1><8.7><81><123><125> Async Serial Driver Patch
|
||
;
|
||
; End of patch code for fix of bugs in the serial driver
|
||
; introduced into the aurora ROM (and hence the F19 overpatch ROM) by the
|
||
; port arbitration code, which was accidently included in those ROMS.
|
||
;_______________________________________________________________________
|
||
;_______________________________________________________________________
|
||
|
||
|
||
|
||
|
||
|
||
;________________________________________________________________________________
|
||
; <8.8> RecoverHandle() patch for 32-bit Memory Manager
|
||
;
|
||
; This patch fixes RecoverHandle so that if the passed block pointer isn't in
|
||
; either the system or app heaps, it makes a last-ditch pass and sees if the
|
||
; pointer points to a ROM resource. If so, great, else it bails with an error.
|
||
; This is especially useful since several new AppleTalk resources are in ROM
|
||
; and their users have a tendency to do RecoverHandles on them because they
|
||
; don't know any better (and shouldn't have to).
|
||
;
|
||
; No traps are patched. These routines are patched into the 32-bit Memory Manager's
|
||
; vector tables in lo-mem at JMemMgr24 ($1E00) and JMemMgr32 ($1F00).
|
||
;________________________________________________________________________________
|
||
|
||
PROC
|
||
EXPORT v24RecoverHandle,v32RecoverHandle
|
||
|
||
;________________________________________________________________________________
|
||
;
|
||
; Routine: v24RecoverHandle,v32RecoverHandle
|
||
;
|
||
; Inputs: A0 -- pointer to block
|
||
; A6 -- pointer to current heap zone
|
||
;
|
||
; Outputs: A0 -- handle to block
|
||
; D0 -- unchanged from input
|
||
; MemErr contains the error code
|
||
;
|
||
; Function: Given a pointer to an alleged heap block, it returns the block's handle.
|
||
;________________________________________________________________________________
|
||
|
||
v24RecoverHandle ; 24 bit version of RecoverHandle
|
||
MOVE.L Lo3Bytes,D2 ; mask to strip extraneous bits
|
||
BRA.S vRecoverHandle
|
||
|
||
v32RecoverHandle ; 32 bit version of RecoverHandle
|
||
MOVEQ #-1,D2 ; no extraneous address bits in 32-bit mode
|
||
|
||
vRecoverHandle
|
||
Move.L BusErrVct,A2 ; save current bus error handler
|
||
LEA RHBusErrHandler,A3 ; our ZC version
|
||
Move.L A3,BusErrVct
|
||
|
||
Move.L -4(A0),A1 ; Handle, or ROMBase on bus error
|
||
|
||
Move.L A2,BusErrVct ;restore old one after danger
|
||
|
||
Add.L A6,A1
|
||
|
||
; The following code tests for bad mp, but can only set MemErr
|
||
|
||
Move.L A0,D1 ; original pointer
|
||
And.L D2,D1 ; stripped to RAW address
|
||
AND.L (A1),D2 ; master pointer value stripped to RAW address
|
||
Sub.L D1,D2 ; if equal, have required error code!
|
||
Beq.S RecoverExit
|
||
|
||
; If we get here, the pointer either didn't point to a block in the suspected
|
||
; heap or is a bogus block pointer. We'll assume it's the first case and try
|
||
; looking in the ROZ created for the ROM resource map before giving up completely.
|
||
; This will not affect the performance of RecoverHandle() since this code is only
|
||
; executed as part of the error path (which shouldn't be taken most of the time).
|
||
|
||
MOVEA.L A6,A3 ; save the previous zone start pointer
|
||
MOVEA.L RomMapHndl,A6 ; get the handle to the ROM resource map
|
||
MOVEA.L (A6),A2 ; and de-reference it
|
||
SUBA.L -4(A2),A6 ; calculate heap start based on rel hdl in MP
|
||
|
||
CMPA.L A3,A6 ; have we been here before?
|
||
BNE.S v32RecoverHandle ; -> no, try again with the ROZ
|
||
|
||
MoveQ #memBCErr,D2 ; block check failure
|
||
RecoverExit
|
||
Move.W D2,MemErr ; stuff global error code (is anybody out there?)
|
||
MoveA.L A1,A0 ; restore A0=handle
|
||
|
||
Move.L vMMNoErrEpilogue,-(SP) ; get MMNoErrEpilogue vector
|
||
RTS
|
||
|
||
|
||
;________________________________________________________________________________
|
||
;
|
||
; RHBusErr -- bus error handler for RecoverHandle
|
||
; A bus error in RecoverHandle causes ROMBase to be jammed for
|
||
; the relative handle.
|
||
; Clear DF bit in frame to inhibit retry of failed read from RAM, and force
|
||
; ROMBase into result, i.e. A1.
|
||
; Input: none
|
||
; Output: potentially forces ROMBase to result field (ultimately A1)
|
||
; Regs: A3
|
||
; Triggered by bus errors in Move.L -4(A0),A1 in RecoverHandle.
|
||
;________________________________________________________________________________
|
||
|
||
RHBusErrHandler
|
||
AndI.W #$FEFF,$A(SP) ;clear DF bits
|
||
Move.L ROMBase,$2C(SP) ;fake Nil value in DIB
|
||
RtE
|
||
|
||
ENDPROC
|
||
;________________________________________________________________________________
|
||
;
|
||
; <8.8> End of RecoverHandle() patch
|
||
;________________________________________________________________________________
|
||
|
||
|
||
;________________________________________________________________________________
|
||
; RMP <12>
|
||
;
|
||
; SetHandleSize() patch for 32-bit Memory Manager
|
||
;
|
||
; This patch fixes A32SetSize not to de-reference off from a nil handle (i.e. A1)
|
||
; when it is called by v32SetHandleSize.
|
||
;
|
||
; No traps are patched. These routines are patched into the 32-bit Memory Manager's
|
||
; vector tables in lo-mem at JMemMgr32+jsetHandleSize ($1F64).
|
||
;________________________________________________________________________________
|
||
|
||
|
||
PROC
|
||
EXPORT v32SetHandleSize
|
||
IMPORT a32SetSize
|
||
|
||
;----------------------------------------------------------------------
|
||
;
|
||
; FUNCTION SetHandleSize(h: Handle; cb: LongInt): result;
|
||
;
|
||
; This routine is used to change the size of a relocatable memory block.
|
||
; The block handle remains the same; the Master Pointer is unchanged if
|
||
; the new length is less than or equal to the old.
|
||
;
|
||
; Arguments:
|
||
; D0 - cb: new block size
|
||
; A0 - handle: pointer to master pointer
|
||
;
|
||
; Result:
|
||
; D0 - 0 => success; memFullErr => failure
|
||
;
|
||
; Registers:
|
||
;
|
||
; A0 - next free block
|
||
; A1 - handle
|
||
;
|
||
|
||
v32SetHandleSize
|
||
BNE.S SHSOk
|
||
|
||
SHSNil
|
||
MoveQ #nilHandleErr,D0 ;return error code
|
||
BrA.S SHSExit
|
||
SHSOk
|
||
BSR.S a32SetSize ;Set size as specified in D0
|
||
SHSExit
|
||
Move.L A1,A0 ;restore A0 for RecoverHandle
|
||
Move.L vMMEpilogue,-(SP) ; get vector to MMEpilogue <v1.9>
|
||
RTS ; jump to it <v1.9>
|
||
|
||
ENDPROC
|
||
;________________________________________________________________________________
|
||
;
|
||
; <12> End of SetHandleSize() patch
|
||
;________________________________________________________________________________
|
||
|
||
|
||
|
||
;________________________________________________________________________________
|
||
; <68> <85>
|
||
;
|
||
; SetPtrSize() patch for 32-bit Memory Manager
|
||
;
|
||
; This patch fixes A32SetSize not to de-reference off from a nil handle (i.e. A1)
|
||
; when it is called by v32SetPtrSize.
|
||
;
|
||
; No traps are patched. These routines are patched into the 32-bit Memory Manager's
|
||
; vector tables in lo-mem at JMemMgr32+jsetptrSize ($1F4C).
|
||
;________________________________________________________________________________
|
||
|
||
PROC
|
||
EXPORT v32SetPtrSize,a32SetSize
|
||
|
||
; addresses in ROM
|
||
a32ActualS EQU $E5A2
|
||
a32GetSize EQU $E5D2
|
||
HBlockMove EQU $E334
|
||
a32MakeSpace EQU $EB40
|
||
ClearGZStuff EQU $E5F2
|
||
SubtractFree EQU $E92A
|
||
A32MakeBkF EQU $DDF4
|
||
AdjustFree EQU $E91C
|
||
A32SetLogSize EQU $E2A0
|
||
a32RelocRel EQU $EC66
|
||
a32SetSizePatch EQU $87996
|
||
|
||
SmartSetSize EQU 1
|
||
|
||
|
||
;----------------------------------------------------------------------
|
||
;
|
||
; FUNCTION SetPtrSize(blk: Ptr; cb: Size): result;
|
||
;
|
||
; This routine is used to set the size of non-relocatable memory blocks
|
||
;
|
||
; Arguments:
|
||
; D0 - cb: new block size
|
||
; A0 - blk: pointer to block data
|
||
; A1 - h: NIL, set up by MMPPrologue
|
||
;
|
||
; Result:
|
||
; D0 - 0 => success; memFullErr => failure
|
||
;
|
||
; Registers:
|
||
;
|
||
; A0 - next free block
|
||
; A1 - current free block
|
||
; A2 - theZone
|
||
; D0 - number of bytes needed
|
||
; D1 - number of bytes in current free block
|
||
; D2 - new block length (temporary)
|
||
;
|
||
v32SetPtrSize
|
||
BSR.S a32SetSize ; set its size <v1.1>
|
||
Move.L vMMEpilogue,-(SP) ; get vector to MMEpilogue <v1.9>
|
||
RTS ; jump to it <v1.9>
|
||
|
||
|
||
; ----- 32 bit version -----
|
||
a32SetSize
|
||
MoveM.L D1-D6/A0-A3,-(SP) ;Save registers. <18Apr85>
|
||
Move.L A0,A2 ;Points to block text. <v1.4>
|
||
Move.B MPtag32-BlkData32(A2),-(SP) ;save flags of block <v1.1>
|
||
Move.L D0,D1 ;Save desired logical size.
|
||
|
||
JSRROM a32ActualS ;
|
||
|
||
Move.L D0,D3 ;New physical size.
|
||
|
||
JSRROM.S a32GetSize ;Get current logical size in D0.
|
||
|
||
Cmp.L D0,D1 ;sNew = sCur?
|
||
BEq @SSEqual ;Yes, return to caller. <121>
|
||
|
||
Move.L A0,A2 ;Points to block text.
|
||
Sub.L #BlkData32,A2 ;Point to block header. <v1.1>
|
||
Move.L BlkSize32(A2),D2 ;Get physical size. <v1.1>
|
||
|
||
Move.L D2,D4 ;Old physical size.
|
||
|
||
Cmp.L D2,D3 ;sNAct = sCAct?
|
||
|
||
BEq @SSLogical ;Yes, just set logical size.
|
||
BCS @SSShrink ;sNAct < sCAct, shrink the block.
|
||
|
||
******************************** Start conditional block. ******************************** <18Apr85>
|
||
|
||
IF SmartSetSize THEN
|
||
|
||
; The block must be grown. <18Apr85>
|
||
; Registers: D0=D3=new phys size; D1=new log size; D2=D4=phys size; D5=?? <18Apr85>
|
||
; A0=text ptr; A1=handle; A2=block ptr; A3=?? <18Apr85>
|
||
; Across the code use registers: <18Apr85>
|
||
; D0=tmp; D1=new log size; D2=D4=phys size; D3=new phys size; D5=delta size <18Apr85>
|
||
; A0=tmp; A1=handle; A2=block ptr; A3=tmp <18Apr85>
|
||
; <18Apr85>
|
||
; First, set up some registers and the GZ's. <18Apr85>
|
||
Move.L D3,D5
|
||
Sub.L D2,D5 ;delta physical size
|
||
Move.L A1,GZRootHnd ;record handle being sized
|
||
Move.L A0,GZRootPtr ;record pointer " "
|
||
|
||
; In this loop, A3 steps across the blocks and D6 accumulates free space. <18Apr85>
|
||
MoveA.L A2,A3
|
||
AddA.L D4,A3 ;next block after growing
|
||
MoveQ #0,D6 ;initial accumulation
|
||
@SSAftFree
|
||
CmpA.L bkLim(A6),A3 ;have we reached the heap end?
|
||
BCC.S @SSAFEnd ;Carry Clear => beyond the end
|
||
|
||
Tst.B (A3) ;Eq => free block
|
||
BNE.S @SSAFEnd
|
||
Add.L BlkSize32(A3),D6 ;accumulate free space <v1.1>
|
||
AddA.L BlkSize32(A3),A3 ;bump on to next block <v1.1>
|
||
BrA.S @SSAftFree ;and continue looping
|
||
@SSAFEnd
|
||
; Detail: be sure to go on if exactly enough space is there -- for no sliding will be done! <18Apr85>
|
||
Sub.L D6,D5 ;D5 := amount unrequited by free space at end
|
||
BLS @SSAsUsual ;Lower or Same => enough space for easy growth!
|
||
|
||
; Provided the block is unlocked, relocatable, try coalescing free space from below, remembering <18Apr85>
|
||
; the 'last' block to give a backward peek when A2 is reached. The logic follows BFindS farily <18Apr85>
|
||
; closely. Starting at the heap's beginning, outer loop skips over allocated blocks (watching <18Apr85>
|
||
; for the one being grown); when a free block is hit, the inner loop starts coalescing until <18Apr85>
|
||
; allocated block (or growing one) is found. The loop terminates with A0 pointing to the last <18Apr85>
|
||
; free block found, and D0 equal to the amount of free space immmediately before the growing block. <18Apr85>
|
||
Move.L A1,D0
|
||
BEq @SSAsUsual ;Eq => it's a ptr, cannot move
|
||
Tst.B (SP) ;remember, the flags were saved earlier
|
||
BMi @SSAsUsual ;Mi => locked, cannot move
|
||
|
||
LEA heapData(A6),A3 ;start with the first block
|
||
@CoalLoop
|
||
CmpA.L A2,A3
|
||
BCC.S @CoalFini ;Carry Clear => beyond growing pointer
|
||
|
||
Tst.B TagBC32(A3) ; <v1.1>
|
||
BEq.S @CoalFree ;Eq => free block found <v1.1>
|
||
Move.L BlkSize32(A3),D0 ;get block size <v1.1>
|
||
AddA.L D0,A3 ;bump up to next block
|
||
MoveQ #0,D0 ;mark 'no immediately preceeding free space'
|
||
BrA.S @CoalLoop
|
||
@CoalFree
|
||
MoveA.L A3,A0 ;start of free space
|
||
MoveQ #0,D0 ;init accumulated free space
|
||
@CoalFLoop
|
||
CmpA.L allocPtr(A6),A3 ;is the rover at a disappearing block? <23Apr85>
|
||
BNE.S @1 ;NotEqual => no... <23Apr85>
|
||
Move.L A0,allocPtr(A6) ;don't let allocptr pt to nonexistent block <23Apr85>
|
||
@1 ; <23Apr85>
|
||
Add.L BlkSize32(A3),D0 ;accumulate free space <v1.1>
|
||
AddA.L BlkSize32(A3),A3 ;bump on to next block <v1.1>
|
||
Tst.B TagBC32(A3)
|
||
BEq.S @CoalFLoop ;Eq => more free space!
|
||
|
||
Clr.L TagBC32(A0) ;clear 1st long word of block <v1.1>
|
||
Move.L D0,BlkSize32(A0) ;update size of coalesced block <v1.1>
|
||
BrA.S @CoalLoop ;continue with this non-free block
|
||
@CoalFini
|
||
|
||
; We exit the above loop with D0=free space immediately below growing block, A0 pointing <18Apr85>
|
||
; to it. If at least 1/4 of the unrequited space can be made up by sliding, DO IT. <18Apr85>
|
||
; In case of a slide: if the free space is within a few minFree's of the needed space, <18Apr85>
|
||
; go the whole way, otherwise slide just enough to meet the needs. <18Apr85>
|
||
; A special case arises: when D5 is tiny, a fourth is zero, and this is BAD news if D0 is <18Apr85>
|
||
; also zero! The test BLS (as opposed to BCS) catches this case along with tinies. <18Apr85>
|
||
; Yet another goof -- must bound unrequited size by minFree, since that's the size of block <18Apr85>
|
||
; of free block we'll make at the end. <18Apr85>
|
||
Move.L D5,D6 ;unrequited space
|
||
LSR.L #2,D6 ;1/4 of it
|
||
Cmp.L D6,D0
|
||
BLS.S @SSNoSlide ;Lower or Same => too little space free (or none available)
|
||
|
||
|
||
MoveQ #minFree32,D6 ;Lower bound for unrequited <v1.2>
|
||
Cmp.L D5,D6
|
||
BLS.S @5 ;Lower or Same => D5 big enough for slide
|
||
Move.L D6,D5 ;Make at least minFree space...
|
||
@5
|
||
MoveQ #minFree32+minFree32,D6 ;unscientific slop <v1.2>
|
||
Add.L D5,D6 ;unrequited space + slop
|
||
Cmp.L D6,D0
|
||
BCS.S @SSFullSlide ;Carry Set => not enough extra to split free space
|
||
|
||
; To do a partial slide, decrement the size of the lower block by the amount we'll slide. <18Apr85>
|
||
Sub.L D5,D0 ;Size minus amount of slide <v1.1>
|
||
Clr.L TagBC32(A0) ;set free block <v1.1>
|
||
Move.L D0,BlkSize32(A0) ;Force size of free block (don't need A0 now)<C883>
|
||
AddA.L D0,A0 ;Target slot for growing block
|
||
Move.L D5,D0 ;Size of slide, for 'sliding' into FullSlide
|
||
|
||
; Full slide code: D0=amt of slide; D4=size of sliding block; D6=tmp; A0=dst of slide; <18Apr85>
|
||
; A1=handle to sliding block; A2=ptr to sliding block. Be sure to update the handle! <18Apr85>
|
||
; And after the block is moved, update GZRootPtr and allocPtr, since the latter may point <18Apr85>
|
||
; to a nonexistent free block. <18Apr85>
|
||
@SSFullSlide
|
||
Move.L A0,(A1) ;new location for sliding/growing block
|
||
Add.L #blkData32,(A1) ;be sure handle points to text of block!!!! <v1.1>
|
||
Move.B (SP),MPtag32(A0) ;restore the tags from home on the stack <v1.1>
|
||
MoveM.L D0/A1,-(SP) ;save amt of slide and handle
|
||
|
||
CmpA.L allocPtr(A6),A2 ;is the rover at the block we're moving? <23Apr85>
|
||
BNE.S @10 ;NotEqual => rover is elsewhere... <23Apr85>
|
||
Move.L A0,allocPtr(A6) ;point rover at new location <23Apr85>
|
||
@10 ; <23Apr85>
|
||
Exg A0,A2 ;A0=src of growing block, A1=dst
|
||
MoveA.L A2,A1 ;dst, for blockmove
|
||
Move.L D4,D0 ;current phys length is length of move!
|
||
;+++ BSr HBlockMove
|
||
JSRROM HBlockMove
|
||
|
||
MoveA.L A2,A0 ;ptr to moved block
|
||
AddA.L D4,A0 ;ptr just beyond -- to new free block
|
||
Move.L (SP)+,BlkSize32(A0) ;stuff size of new free block <v1.1>
|
||
Clr.L TagBC32(A0) ;free block <v1.1>
|
||
MoveA.L (SP)+,A1 ;restore handle
|
||
|
||
LEA blkData32(A2),A0 ;text ptr to growing block
|
||
Move.L A0,GZRootPtr
|
||
BrA.S @SSAsUsual
|
||
|
||
; Our last resort: check the block following ours; if it's larger and allocated, don't even <18Apr85>
|
||
; bother trying to move it. <18Apr85>
|
||
@SSNoSlide
|
||
MoveA.L A2,A0
|
||
AddA.L D4,A0 ;ptr to following block
|
||
Move.L BlkSize32(A0),D0 ;get size <v1.1>
|
||
Cmp.L D0,D3
|
||
BCC.S @SSAsUsual ;Carry Clear => new size is large, so go the normal route
|
||
Tst.B TagBC32(A0)
|
||
BNE.S @SSDoReloc ;Not Equal => larger, alloc block following
|
||
|
||
********************************* End conditional block. ******************************** <18Apr85>
|
||
ENDIF ; SmartSetSize
|
||
|
||
; This resumes the original SetSize growth code. The register setup must be adjusted to: <18Apr85>
|
||
; D0=??; D1=new log size; D2=D4=phys size; D3=new phys size; D4=phy size; D5=??; D6=?? <18Apr85>
|
||
; A0=??; A1=handle; A2=block ptr; A3=?? <18Apr85>
|
||
@SSAsUsual
|
||
Move.L A2,A0 ;Points to block header.
|
||
Move.L D3,D0 ;New physical size.
|
||
Sub.L D2,D0 ;Compute delta bytes.
|
||
Add.L D2,A2 ;Point to where space is needed
|
||
|
||
; doesn't move it by accident.
|
||
BSet #Lock,MPtag32(A0) ;lock block <v1.1>
|
||
|
||
JSRROM a32MakeSpace ;Try making room after this block.
|
||
|
||
BClr #Lock,MPtag32(A0) ;Unlock block <v1.1>
|
||
@200 Move.L A2,D4 ;Did we succeed?
|
||
BNE.S @SSEnough ;Yes, keep going
|
||
|
||
; New entry point to bypass MakeSpace when following block is bigger than one we're growing. <18Apr85>
|
||
@SSDoReloc
|
||
Move.L A1,D4 ;No, maybe we can relocate block.
|
||
BEq.S @SSFail ;No, block is Non-Relocatable.
|
||
Tst.B (SP) ;Can we move the growing block?
|
||
BMi.S @SSFail ;No, block is locked.
|
||
Move.L D1,D0 ;Desired new logical size.
|
||
|
||
|
||
; Try to grow the (unlocked) block by relocating&growing simultaneously. Across the call <10Apr85>
|
||
; mark it nonpurgeable, since we WANT it! Note must retrieve previous state from stack <10Apr85>
|
||
; unlike the BSet/BClr pair bracketing MakeSpace above. To get here, the Lock bit must be <10Apr85>
|
||
; clear, so the blithe BClr above jibes with our restoration from the stack. <10Apr85>
|
||
Move.L (A1),A3 ;dereference handle <v1.1>
|
||
BClr #Purge,MPtag32-BlkData32(A3);Unlock block <v1.1>
|
||
JSRROM a32RelocRel ;Relocate the old block into a new.
|
||
|
||
Move.L (A1),A0 ; get new address of block header <121>
|
||
Sub.L #BlkData32,A0 ;Point to block header. <121>
|
||
|
||
; MOVE.B (SP),MPtag32-BlkData32(A3) ;Restore previous state. <v1.1>
|
||
JSRROM ClearGZStuff ;mark gz stuff as done
|
||
BrA.S @SSExit ;Return to caller.
|
||
@SSFail ;Unable to find space.
|
||
JSRROM ClearGZStuff ;mark gz stuff as done
|
||
MoveQ #memFullErr,D0 ;Not enough room to reloc. block.
|
||
BrA.S @SSExit ;Return to caller.
|
||
@SSEnough ;Enough room has been found.
|
||
JSRROM ClearGZStuff ;mark gz stuff as done
|
||
Move.L BlkSize32(A2),D0 ;Length of free space after. <v1.1>
|
||
Move.L D0,D4 ;Physical size of free space.
|
||
Add.L D2,D4 ;Physical size of new combined blk.
|
||
Move.L A0,A2 ;Points to block.
|
||
Move.L D4,BlkSize32(A2) ;set block physical size. <v1.1>
|
||
; Neg.L D0 ;Minus size of new space.
|
||
; BSR.S AdjustFree ;Account for less free space.
|
||
JSRROM SubtractFree ;Account for less free space. <v1.7>
|
||
@SSShrink ;Shrink the block.
|
||
Sub.L D3,D4 ;Number of bytes to shrink block.
|
||
Cmp.L #MinFree32,D4 ;sFree < MinFree? <v1.2>
|
||
BCS.S @SSLogical ;Yes, set logical size only.
|
||
BTST #ROZ,flags(A6) ;don't shrink ROZ blocks <04Mar85>
|
||
BNE.S @SSSkip ; <04Mar85>
|
||
|
||
Move.L A2,A0 ;Points to block.
|
||
Add.L D3,A0 ;Point to new free block.
|
||
Move.L D3,BlkSize32(A2) ;set block physical size. <v1.1>
|
||
Move.L D4,D0 ;Size of new free block.
|
||
JSRROM a32MakeBkF ;Release free space.
|
||
JSRROM AdjustFree ;And account for new free space.
|
||
@SSLogical ;Set the logical size of the block.
|
||
Move.L A2,A0 ;Points to block.
|
||
Move.L D1,D0 ;New logical size.
|
||
JSRROM a32SetLogSize ;Set logical size.
|
||
@SSDone
|
||
MoveQ #0,D0 ;Success result code.
|
||
@SSExit
|
||
|
||
; Move.L (A1),A3 ;dereference handle <v1.1>
|
||
; Move.B (SP)+,MPtag32-BlkData32(A3) ;Restore MP flag byte. <v1.1>
|
||
|
||
Move.B (SP)+,MPtag32(A0) ;Restore MP flag byte. <v1.1>
|
||
@SSFin
|
||
MoveM.L (SP)+,D1-D6/A0-A3 ;Restore registers. <18Apr85>
|
||
RTS ;Return to caller.
|
||
@SSSkip
|
||
MoveQ #memROZWarn,D0 ; <04Mar85>
|
||
BRA.S @SSExit ; <04Mar85>
|
||
@SSEqual
|
||
Move.B (SP)+,D0 ; Don't care about saved MP flag <121>
|
||
MoveQ #0,D0 ;Success result code. <121>
|
||
Bra.S @SSFin ; <121>
|
||
|
||
ENDPROC
|
||
;________________________________________________________________________________
|
||
;
|
||
; <68><85> End of SetPtrSize() patch
|
||
;________________________________________________________________________________
|
||
|
||
|
||
|
||
|
||
;________________________________________________________________________
|
||
;
|
||
; <54> Rolled over changes from split-off sources on 4/16/90 by DDG
|
||
;
|
||
; Patch To IOPMsgRequest Trap to Fix IOP Serial Driver Control Call Bug
|
||
;
|
||
; Traps Patched: IOPMsgRequest
|
||
;
|
||
; The problem: IOP Serial Driver calls are being mis-queued because
|
||
; the control rtn is jumping to IODone before the control calls are
|
||
; actually completed on the 6502 side.
|
||
;
|
||
; The fix: to make the patch small, and because the control calls call
|
||
; the IOPMsgRequest trap, we do a come-from patch on that trap. If the
|
||
; 'come from' addresses match any of those in the driver, then the patch
|
||
; code is exectued. Else the ROM code (or previous patch) is jumped to.
|
||
; All the patch code does is jsr to the ROM code, then wait around for
|
||
; the IOP request to have completed before returning.
|
||
;
|
||
;________________________________________________________________________
|
||
proc
|
||
export IOPMsgRequest
|
||
;offsets to ROM addresses
|
||
IOPControlNormal EQU $6B932
|
||
IOPControl08 EQU $6B95A
|
||
IOPControl13 EQU $6B9C2
|
||
|
||
with IOPRequestInfo
|
||
IOPMsgRequest
|
||
|
||
; We can use the new protection scheme, if the first two instructions in the <115>
|
||
; patch are a bra.s followed by the jump to the old rom address.
|
||
|
||
bra.s @protection
|
||
@toRom
|
||
BackToTrap OldIOPMsgRequest ; no, then just execute ROM Code
|
||
@protection
|
||
|
||
cmpRA IOPControlNormal,OSTrapReturnAddressDepth(sp) ; from IOP serial drvr ctl call?
|
||
beq.s @doPatch ; yes, then come back here
|
||
cmpRA IOPControl08,OSTrapReturnAddressDepth(sp)
|
||
beq.s @doPatch
|
||
cmpRA IOPControl13,OSTrapReturnAddressDepth(sp)
|
||
bne.s @toRom
|
||
|
||
@doPatch move.l a0,-(sp) ; ROM IOPMsgRequest does not save a0
|
||
bsr.s @toRom ; bsr to IOPMsgRequest in ROM
|
||
move.l (sp)+,a0
|
||
|
||
@syncLoop tst.b irReqActive(a0)
|
||
bne.s @syncLoop
|
||
rts
|
||
|
||
endwith
|
||
endproc
|
||
|
||
;_______________________________________________________________________________
|
||
;
|
||
; <54> End of Patch To IOPMsgRequest Trap to Fix IOP Serial Driver Control Call Bug
|
||
;_______________________________________________________________________________
|
||
|
||
|
||
|
||
|
||
;____________________________________________________________________________ GGD <28>
|
||
; Patch the Deferred Task Manager Task Dispatcher to re-enable interrupts upon
|
||
; exiting to fix QuickMail servers (for now at least), because they call through
|
||
; jDisptch at application level and wind up with all interrupts being masked,
|
||
; and the Task Dispatcher expects to only be called from then end of an interrupt
|
||
; handler, which will restore the interrupt level via an RTE. Note that Applications
|
||
; should NOT be calling through this UNDOCUMENTED LOW MEMORY VECTOR, and we are
|
||
; changing this just so QuickMail servers don't hang with interrupts disabled,
|
||
; until CE Software can fix their bug.
|
||
|
||
NewvDisptch proc export
|
||
JsrTrap ROMvDisptch ; call the existing ROM code
|
||
andi.w #$F8FF,sr ; enable all interrupts
|
||
rts ; all done
|
||
endproc
|
||
|
||
; End of Deferred Task Manager Task Dispatcher Patch Installation
|
||
;____________________________________________________________________________ GGD <28>
|
||
|
||
;____________________________________________________________________________ jwk <29>
|
||
;
|
||
; BusErrHandler -- New and improved chaining SCSI bus error handler.
|
||
; When the SCSI Mgr is performing a blind data transfer, it patches
|
||
; out the bus error vector. The old SCSI Mgr bus error handler
|
||
; assumed that if it got called, it must be handling a SCSI bus error.
|
||
; Unfortunately, NuBus cards could bus error while the SCSI Mgr is
|
||
; installed. To be a better bus error citizen, the SCSI bus error
|
||
; handler now checks for a SCSI address as the fault address, and
|
||
; chains to the bus error handler that it replaced.
|
||
;
|
||
BusErrHandler: PROC EXPORT
|
||
|
||
ROMBusErrRecovery EQU $00008a6c ; recovery delay routine in ROM <29>
|
||
|
||
move.l d0,-(sp) ; save d0 <29>
|
||
moveq.l #$ffffff9c,d0 ; mask = $ffffff9c <start>
|
||
and.l 4+$10(sp),d0 ; clear variable bits of the fault address
|
||
cmp.l SCSIHsk,d0 ; was it a SCSI chip access ?
|
||
beq.s @start ; if so, start processing the bus error
|
||
|
||
move.l (sp)+,d0 ; restore d0
|
||
move.l OldBusErrVct(a6),-(sp) ; put old bus error handler addr on stack <end>
|
||
rts ; jump to old handler, assuming it'll RTE <29>
|
||
|
||
@start
|
||
|
||
subq.w #1,BusErrCount(a6) ; retry until we get tired
|
||
beq.s CleanUp
|
||
|
||
jmpROM ROMBusErrRecovery ; back off and try again (RTE) <29>
|
||
|
||
Cleanup
|
||
addq.l #4,sp ; throw away copy of d0 on stack <29>
|
||
|
||
move.w (sp),d0 ; get sr from stack
|
||
bfextu 6(sp){0:4},d1 ; get format code from stack
|
||
cmp.b #$0A,d1 ; short exception frame?
|
||
bne.s Drop46w ; no, so use larger frame
|
||
adda.w #16*2,sp ; dispose of the 16-word frame
|
||
bra.s DummyFrame ; and finish up
|
||
Drop46w
|
||
add.w #46*2,sp ; size of exception frame
|
||
DummyFrame
|
||
;
|
||
; Fake a format code 0 exception frame (4 words) to finish cleaning up
|
||
;
|
||
move.w zeroReg,-(sp) ; format code 0
|
||
pea FinishErr ; PC value
|
||
move.w d0,-(sp) ; sr value
|
||
rte ; 'return' from the fake exception
|
||
|
||
FinishErr
|
||
moveq.l #scBusTOErr,d0 ; assume slow peripheral
|
||
btst.b #bPM,sBSR(a3) ; phase change? <C478/10Dec86> <v1.5><29>
|
||
bne.s @ErrorDone ; phase matches: slow peripheral
|
||
moveq.l #scPhaseErr,d0 ; return phase change error
|
||
@ErrorDone
|
||
rts
|
||
|
||
;
|
||
; End of chaining SCSI bus error handler patch
|
||
;____________________________________________________________________________ jwk <29>
|
||
|
||
;_________________________________________________________________________________________ <119> djw
|
||
; Beginning code for Quantum 7.9 ROM fix
|
||
;
|
||
; Detailed description of the Quantum problem and solution:
|
||
;
|
||
; Quantum drives with the firmware version 7.9, has a problem with loosing the last byte
|
||
; of a block during a multi-block write. The problem occurs when the time between blocks
|
||
; written to the SCSI bus on the CPU side, is greater than 482 microseconds. This may
|
||
; occur in situations where there are a lot of interrupts. When conditions are right and
|
||
; the problem happens, the last byte of the previous block (in a multi-block transaction),
|
||
; is "eaten" by the drive. Any checksum or CRC calculated by the drive is correct,
|
||
; because the drive calculates it after the byte has been corrupted. This problem is
|
||
; especially frequent when email packages are installed on the Mac, since they generate
|
||
; a lot of interrupts which take a long time. This problem only occurs during fast
|
||
; writes in the SCSI manager (pseudo-dma mode).
|
||
;
|
||
; The way the SCSI manager currently works is it gets a TIB packet which contains the
|
||
; instructions on how to talk to a particular device. Included in the TIB is when to
|
||
; re-synchronize with the drive by waiting for a *REQ. When we see *REQ, the SCSI
|
||
; manager then begins the next TIB data transfer instruction and loads a byte of data
|
||
; into the 53C80's output register. After the first byte is "manually" sent, the
|
||
; hardware handshaking automatically takes care of the *REQ and *ACK handshaking. When
|
||
; the TIB write transfer is complete, pseudo-dma is disable, which releases *ACK,
|
||
; completing the handshake. This allows the target to assert *REQ when it is ready.
|
||
;
|
||
; The window of vulnerability is between the last byte of the previous block and the
|
||
; first byte of the next block. More correctly, it is between the rising edge of *ACK
|
||
; and the falling edge of the next *ACK. Because we release *ACK to synchronize, an
|
||
; interrupt may come in and delay the next transfer.
|
||
;
|
||
; The solution to the problem is to pre-load a data byte into the 53C80's data output
|
||
; register before we release *ACK. There are two ways of releasing *ACK: disable pseudo
|
||
; dma, and write a byte to the data output register. Leaving pseudo-dma enabled through
|
||
; the entire TIB will mean that whenever a *REQ occurs, there will be data available in
|
||
; the output register. This means there will be no delay between bytes because the
|
||
; hardware is not subject to interrupt delays.
|
||
;
|
||
; This patch therefore involves patching the TIB interpreter and the fast write routine
|
||
; in the SCSI manager. There are five versions of the SCSI manager to patch: Mac Plus,
|
||
; SE, Mac II, Portable, and IIci.
|
||
;
|
||
;_________________________________________________________________________________________
|
||
; QuantumWBlindIIci - patch to NewSCSIWBlind
|
||
;
|
||
; This code replaces the original NewSCSIWBlind entry point. The new entry for blind
|
||
; writes enables pseudo-dma on a per-transaction basis. Pseudo-dma was previously
|
||
; enabled only on a per-TIB-instruction basis. We jump back into the ROM to the original
|
||
; entry point to continue executing the TIB.
|
||
;
|
||
; Input: reg a3 = base of SCSI read addr
|
||
; a6 = SCSI stack frame
|
||
; d7 = zero
|
||
;
|
||
Export QuantumWBlindIIci
|
||
Export FastWriteFix
|
||
|
||
QuantumWBlindIIci
|
||
|
||
romNewSCSIWBlind Equ $07574 ; rom offset to NewSCSIWBlind entry point
|
||
|
||
move.b d7,sTCR+WrOffs(a3) ; set to match data out phase (to zero)
|
||
move.b #iDMA,sMR+WrOffs(a3) ; enable DMA in mode register
|
||
move.b #iDB,sICR+WrOffs(a3) ; assert data bus in initiator command reg
|
||
move.b d7,sDMAtx+WrOffs(a3) ; start write DMA
|
||
|
||
; Do I need to test for DRQ or *REQ at this point?
|
||
|
||
jmp ([RomBase],romNewSCSIWBlind); continue at original entry pt in ROM
|
||
|
||
|
||
|
||
;_________________________________________________________________________________________
|
||
; FastWriteFix - patch to FastWrite
|
||
;
|
||
; This code replaces the low level data transfer routine for fast writes in the SCSI
|
||
; manager. It is rewritten to assume psuedo-dma is always on, and to do the device
|
||
; synchronization (looking for *REQ and DRQ), after loading a data byte into the
|
||
; output register of the 5380. We don't have to worry about zero-byte transfers. They
|
||
; are filtered out in the calling routine (Transfer).
|
||
;
|
||
; Entry: d2 = number of bytes to transfer
|
||
; a1 = addr of sBSR(a3) - by convention, and used by bus error handler
|
||
; a2 = ptr to data buffer to transfer
|
||
; a3 = base addr of NCR 53C80
|
||
; a4 = ptr to SCSI globals
|
||
;
|
||
; Exit: d1 = number of bytes actually transfered. This value is only good if
|
||
; the transfer was good with no errors. It is inaccurate when an
|
||
; error aborts the transfer.
|
||
|
||
With scsiGlobalRecord
|
||
|
||
FastWriteFix
|
||
|
||
move.l hhsk5380(a4),a0 ; point to addr for hardware handshaking
|
||
adda.w wrOffset(a4),a0 ; add in write offset
|
||
move.l d2,d1 ; save to return number of bytes transfered
|
||
|
||
; Pre-load the NCR 53C80's output register with a byte of data. If we are in
|
||
; the middle of a multi-block write, *ACK is currently asserted. Writing a byte
|
||
; to the output register will release *ACK, completing the handshaking, allowing
|
||
; the target to assert *REQ. Is there a chance We do not need to check for DRQ at this point (to see
|
||
; if the chip is ready for the next byte), because all data out routines always
|
||
; wait to make sure the last byte got out.
|
||
|
||
sub.l #1,d2 ; dec number of bytes to xfer
|
||
move.b (a2)+,(a0) ; write data byte to output register
|
||
|
||
; With *ACK released, determine if the target is in sync. We cannot look for
|
||
; *REQ to be asserted, because the target may have already accepted the data byte
|
||
; and released *REQ at this point. We can sync on DRQ which will signal when
|
||
; the NCR 53C80 is ready to accept a data byte, meaning a *REQ from the target
|
||
; must have already occurred and our data byte was taken.
|
||
|
||
@syncWait
|
||
btst.b #bDMAR,(a1) ; check bus & status reg for DRQ
|
||
bne.s @doWrite ; DRQ present - sync-ed up so proceed
|
||
btst.b #bREQ,sCSR(a3) ; no DRQ - is *REQ present ?
|
||
beq.s @syncWait ; no *REQ yet - wait for sync
|
||
btst.b #bPM,(a1) ; with *REQ, check phase lines
|
||
bne.s @syncWait ; still in data out phase - wait
|
||
moveq.l #0,d1 ; out of phase - did not xfer any bytes
|
||
moveq.l #scPhaseErr,d0 ; return error
|
||
bra.s @Done ; exit
|
||
|
||
; Perform the write to the SCSI chip. First align the bytes to longs, then
|
||
; align them to 32 byte chunks. Transfer the bulk of the data in 32 byte
|
||
; blocks.
|
||
; Reg d2.l = number of bytes to move
|
||
|
||
@doWrite
|
||
cmpi.l #3,d2 ; check for very short copy
|
||
bls.s @veryShort ; skip alignment if very short
|
||
|
||
move.l a2,d0 ; get addr of data buffer
|
||
andi.l #$00000003,d0 ; check for long word alignment
|
||
beq.s @Aligned ; if no alignment needed
|
||
subq.l #4,d0 ; bias by 4 to get correct index
|
||
jmp @Aligned(d0.w*2) ; do the alignment
|
||
move.b (a2)+,(a0) ; move a byte
|
||
move.b (a2)+,(a0) ; move a byte
|
||
move.b (a2)+,(a0) ; move a byte
|
||
@Aligned
|
||
add.l d0,d2 ; adjust the byte count (d0 = neg)
|
||
move.l d2,d4 ; save tail byte count
|
||
lsr.w #2,d2 ; adjust to number of longs to move
|
||
moveq.l #7,d0 ; mask for starting index
|
||
and.l d2,d0 ; number of long words to move first
|
||
neg.w d0 ; negate to index backwards
|
||
lsr.l #3,d2 ; number of 32 byte blocks to move
|
||
move.l d2,d3 ; get number of 32*64K byte blks to move
|
||
swap d3 ; count in low word
|
||
jmp @CopyStart(d0.w*2) ; jump into the loop
|
||
|
||
@CopyLoop move.l (a2)+,(a0) ; move a 32 byte block of data....
|
||
move.l (a2)+,(a0) ; ... 4 bytes at a time
|
||
move.l (a2)+,(a0)
|
||
move.l (a2)+,(a0)
|
||
move.l (a2)+,(a0)
|
||
move.l (a2)+,(a0)
|
||
move.l (a2)+,(a0)
|
||
move.l (a2)+,(a0)
|
||
@CopyStart dbra d2,@CopyLoop ; loop in chunks of 32 bytes
|
||
dbra d3,@CopyLoop ; loop in chunks of 32*64K bytes
|
||
|
||
andi.l #$00000003,d4 ; check for tail alignment
|
||
move.l d4,d2 ; d2 = number of bytes remaining
|
||
|
||
@veryShort
|
||
neg.w d2 ; negate to index backwards
|
||
jmp @Remaining(d2.w*2) ; write remaining bytes
|
||
move.b (a2)+,(a0) ; move a byte
|
||
move.b (a2)+,(a0) ; move a byte
|
||
move.b (a2)+,(a0) ; move a byte
|
||
@Remaining
|
||
|
||
; Before exiting this routine, make sure that the peripheral has actually accepted
|
||
; the data byte. Wait for a DRQ (meaning the SCSI chip is ready for another byte)
|
||
; before exiting.
|
||
|
||
@DoneWait
|
||
moveq.l #0,d0 ; set good return
|
||
|
||
btst.b #bDMAR,(a1) ; check for DRQ (a1 = sBSR(a3))
|
||
bne.s @Done ; if DRQ, peripheral got the byte
|
||
btst.b #bREQ,sCSR(a3) ; no DRQ - is *REQ present ?
|
||
beq.s @DoneWait ; no *REQ yet - wait for it
|
||
btst.b #bPM,(a1) ; are we still in phase ?
|
||
bne.s @DoneWait ; if so, keep waiting
|
||
|
||
@Done
|
||
rts ; we're done
|
||
|
||
Endp ; end scsi patches
|
||
|
||
|
||
;____________________________________________________________________________ EH <33><37>
|
||
;
|
||
; Patch To IOPMoveData Trap to Fix IOP Serial Driver DMA Hang Bug
|
||
;
|
||
; Traps Patched: IOPMoveData
|
||
;
|
||
; The problem: the iop serial DMA hangs at if more than one byte
|
||
; accumulates in the SCC fifo. This is really a problem with the
|
||
; timing in the DMA hardware, but we'll work around it in software.
|
||
;
|
||
; The fix: In the main driver loop, we'll manually remove extra
|
||
; bytes from SCC fifo to DMA buffer before restarting the DMA.
|
||
;
|
||
; Note:If one of these manually moved bytes is in error, it will be
|
||
; bucketed (not moved to DMA buffer), as will subsequent bytes in the
|
||
; fifo.
|
||
;
|
||
; MECHANISM: To make the patch small, we do a come-from on IOPMoveData.
|
||
; We use the ROM IOPMove Data to download the patches to the 6502 code
|
||
; after we've already downloaded the unpatched image.
|
||
;
|
||
; <37> added in two fixes.
|
||
; Fix slow baud rate chars getting munched if a control call is made to
|
||
; change the baud rate. Now we wait for an ALL SENT from the SCC before
|
||
; dispatching all control calls.
|
||
;
|
||
; Fix CTS status on open to be reported properly back to 68000 side.
|
||
; We now properly set CTSFlag value during the open call, which is the
|
||
; value that gets reported in the status call.
|
||
;
|
||
; <123> added in external control call feature
|
||
; -- Use bit 6 now of the CtlOptions byte in control call 16
|
||
; bit 6 = 0 means internal clocking
|
||
; bit 6 = 1 means external clocking
|
||
; -- Incidentally, fixed bug in break handling code such that the null
|
||
; char is now discarded when break is de-asserted.
|
||
; -- changed ExtStatInt handler code to set bit 3 of Async Err if break is rcv'd.
|
||
; -- changed InitSCC rtn to check for ext clocking in setting WR4 clock divide bits.
|
||
; we also disable HWHS for the external clock case so we won't try to use the
|
||
; CTS line for clocking AND handshaking.
|
||
; -- changed the EXTInt handler to disable CTS interrupts if we receive them
|
||
; too quickly. This was never implemented in the IOP driver.
|
||
; Note we are doing a slime-bucket thing here by using ZP addresses that the ROM
|
||
; driver isn't using. But it doesn't look like anybody's using it, so hey, what
|
||
; the living heck. ZPSize is 32, so we'll start our stuff at offset $33.
|
||
; CTSCount = ZPBase+$33 the count of CTS transitions we started timing
|
||
; LastTime = ZPBase+$34 the last timer value (low byte) for a CTS interrupt
|
||
; -- Modify the Zero Page initialization to clear all $55 bytes we have
|
||
;
|
||
; <126>
|
||
; -- fix disable to HWHS for external clocking. it now gets disabled write before
|
||
; CtlOptions (#16) calls DoInitSCC instead of in the InitSCC routine.
|
||
; -- rolled in a fix to close that i had meant to add in <123>. We time out now
|
||
; on waiting for the all-sent on the close.
|
||
;
|
||
; <138>
|
||
; -- fix the IOP timer to actually count! i think the code to disable CTS interrupts
|
||
; was just working by chance, since i'm also fixing a branch instruction in
|
||
; that code to fix the bug with printing to the imagewriter.
|
||
;________________________________________________________________________
|
||
IOPMoveDataPatch proc
|
||
export IOPMoveData
|
||
|
||
;offsets to ROM addresses
|
||
From_IOPOpenCall EQU $0006bC48 ;return addr of IOPMoveData call in IOP Serial Open
|
||
ROM_IOPMoveData EQU $00004ed2 ;rom addr for the trap
|
||
|
||
;Pic RAM addresses
|
||
DrvrAPicAddr EQU $2d55 ; driver A start addr for Pic RAM
|
||
DrvrBPicAddr EQU $56aa ; driver B start addr for Pic RAM
|
||
|
||
numPatches EQU 24 ; number of times thru loop
|
||
PatchDrvrSize EQU $09ae ; size of the patched driver
|
||
|
||
;__________________________________________________________
|
||
;
|
||
; 6502 IOP Driver Patches -- code to fix in downloaded image.
|
||
; Patches are in order by offset from beginning of driver.
|
||
; Each set of patch bytes is preceded by a word offset to
|
||
; start of patch, and a byte for size of patch.
|
||
;
|
||
; There is one set of patches for Driver A and one for Driver B.
|
||
;__________________________________________________________
|
||
DrvrAFix
|
||
|
||
; changes zero page init to clear all $55 bytes
|
||
; this one-byte change is inline.
|
||
dc.b $00,$09 ; offset to this patch
|
||
dc.b @a20end-@a20 ; number patchbytes
|
||
|
||
@a20 dc.b $55 ; y<-$55, the index to clear out z-page
|
||
|
||
; fixes the new location of the driver buffers
|
||
; new buffer start addr is $3703 = $2d55(base) + $9ae(new offset)
|
||
@a20end dc.b $00,$46 ; offset to this patch
|
||
dc.b @a1end-@a1 ; number patchbytes
|
||
|
||
@a1 dc.b $a9,$37 ; lda #>Buffers (new high byte)
|
||
dc.b $a2,$03 ; lda #>Buffers (new low byte)
|
||
|
||
; fix one byte to load into DMA count
|
||
@a1end dc.b $00,$94 ; offset to this patch
|
||
dc.b @a2end-@a2 ; number patchbytes
|
||
|
||
@a2 dc.b $FB ; put FB in the DMA count instead of FF
|
||
|
||
; calls the fix to start the IOP timer since
|
||
; patch wouldn't fit inline
|
||
@a2end dc.b $00,$98 ; offset to this patch <138>
|
||
dc.b @a23end-@a23 ; number patchbytes <138>
|
||
; <138>
|
||
@a23 dc.b $4C,$f8,$36 ; jmp to fix at addr $36f8 = $2d55(base) +$9a3(offset) <138>
|
||
|
||
; calls the fix to CTSFlag on Open (see patch at $8D5) since the
|
||
; patch wouldn't fit inline
|
||
@a23end dc.b $01,$00 ; offset to this patch <37>
|
||
dc.b @a3end-@a3 ; number patchbytes <37>
|
||
; <37>
|
||
@a3 dc.b $4C,$2b,$36 ; jmp to fix at addr $362B = $2d55(base) +$8D6(offset) <37>
|
||
|
||
; calls the fix to DoPollEvent (see patch at $880) since the
|
||
; patch wouldn't fit inline
|
||
@a3end dc.b $01,$2F ; offset to this patch
|
||
dc.b @a4end-@a4 ; number patchbytes
|
||
|
||
@a4 dc.b $20,$D5,$35 ; jsr to fix at address $2d55(base) +$880(offset)
|
||
|
||
; calls the fix to DMA code (see patch at $886) since the
|
||
; patch wouldn't fit inline
|
||
@a4end dc.b $01,$46 ; offset to this patch
|
||
dc.b @a5end-@a5 ; number patchbytes
|
||
|
||
@a5 dc.b $F0,$03 ; beq to just below
|
||
dc.b $4C,$db,$35 ; jmp here if DMA was NOT stopped by interrupt rtn $2d55(base)+$886(offset)
|
||
dc.b $4C,$02,$36 ; jmp here if DMA was stopped by interrupt rtn $2d55(base)+$8ad(offset)
|
||
|
||
|
||
; fix one byte to load into DMA count
|
||
@a5end dc.b $01,$6E ; offset to this patch
|
||
dc.b @a6end-@a6 ; number patchbytes
|
||
|
||
@a6 dc.b $FB ; put FB in the DMA count instead of FF
|
||
|
||
; calls patch to close to time-out on the all sent loop since the
|
||
; patch wouldn't fit inline
|
||
@a6end dc.b $02,$6F ; offset to this patch
|
||
dc.b @a21end-@a21 ; number patchbytes
|
||
|
||
@a21 dc.b $4C,$e0,$36 ; jmp to fix at address $36e0 = $2d55(base) +$98b(offset) <37>
|
||
|
||
; calls the fix to all sent in control calls (see patch at 8C6) since the <37>
|
||
; patch wouldn't fit inline <37>
|
||
@a21end dc.b $03,$39 ; offset to this patch <37>
|
||
dc.b @a7end-@a7 ; number patchbytes <37>
|
||
; <37>
|
||
@a7 dc.b $4C,$1b,$36 ; jmp to fix at address $361b = $2d55(base) +$8C6(offset) <37>
|
||
|
||
; calls patch to add ext clking to control call 16 since the
|
||
; patch wouldn't fit inline
|
||
@a7end dc.b $4,$4a ; offset to this patch
|
||
dc.b @a12end-@a12
|
||
|
||
@a12 dc.b $4c,$38,$36 ; jump to fix at address $3638= $2d55(base) + $8e3(offset)
|
||
|
||
; calls patch to disable CTS interrupts if we get them too fast since
|
||
; patch wouldn't fit inline
|
||
@a12end dc.b $07,$36 ; offset to this patch
|
||
dc.b @a18end-@a18
|
||
|
||
@a18 dc.b $4c,$b5,$36 ; jump to fix at address $36b5= $2d55(base) + $960(offset)
|
||
|
||
; calls patch to set bit 3 of AsyncErr if break received since
|
||
; patch wouldn't fit inline
|
||
@a18end dc.b $07,$55 ; offset to this patch
|
||
dc.b @a14end-@a14
|
||
|
||
@a14 dc.b $4c,$82,$36 ; jump to fix at address $3682= $2d55(base) + $92d(offset) <126>
|
||
|
||
; calls patch to set clock divide bits for WR4 since
|
||
; patch wouldn't fit inline
|
||
@a14end dc.b $07,$79 ; offset to this patch
|
||
dc.b @a16end-@a16
|
||
|
||
@a16 dc.b $4c,$a1,$36 ; jump to fix at address $36a1= $2d55(base) + $94c(offset) <126>
|
||
|
||
; fixes the code at DoPollEvent to compare to DMA count,
|
||
; not the DMA address.
|
||
@a16end dc.b $08,$80 ; offset to this patch
|
||
dc.b @a8end-@a8 ; number patchbytes
|
||
|
||
@a8 dc.b $AD,$23,$F0 ; lda DMACntLo
|
||
dc.b $C9,$FB ; cmp #$FB
|
||
dc.b $60 ; rts
|
||
|
||
; fixes DMA code to check for bytes left over in the SCC fifo
|
||
@a8end dc.b $08,$86 ; offset to this patch
|
||
dc.b @a9end-@a9 ; number patchbytes
|
||
|
||
@a9 dc.b $AD,$22,$F0 ; lda DMA_AddrHi Set up temp pointer
|
||
dc.b $85,$5A ; sta TempBufPtr+1 into the DMA buffer. $55(base)+$05(offset)
|
||
dc.b $64,$59 ; stz TempBufPtr $55(base)+$04(offset)
|
||
dc.b $AC,$21,$F0 ; ldy DMA_AddrLo Get the byte offset into buffer
|
||
;@NxtChar
|
||
dc.b $AD,$41,$F0 ; lda SCC_Ctl Read RRO
|
||
dc.b $29,$01 ; and #Rx_CharAvail is there a receive char?
|
||
dc.b $F0,$2B ; beq @Done no chars, then we are done
|
||
dc.b $AD,$43,$F0 ; lda SCC_Data get the data char
|
||
dc.b $91,$59 ; sta (TempBufPtr),y store char in buffer $55(base)+$04(offset)
|
||
dc.b $84,$7F ; Sty HoldDMACount $55(base)+$2a(offset)
|
||
dc.b $C8 ; iny
|
||
; if any errors reset the scc
|
||
dc.b $A9,$01 ; lda #1 read RR1
|
||
dc.b $8D,$41,$F0 ; sta SCC_Ctl
|
||
dc.b $AD,$41,$F0 ; lda SCC_Ctl
|
||
dc.b $29,$70 ; and #$70 parity, overrun, framing err?
|
||
dc.b $85,$5E ; sta HoldRR1 save errors $55(base)+$09(offset)
|
||
dc.b $F0,$E3 ; beq @NxtChar no get the next char
|
||
; Suppose Special Rx Int has turned off DMA.
|
||
; There could be chars in FIFO after interrupt.
|
||
; Driver only flags errors on last byte DMAd in.
|
||
; To insure this, drop all bytes after error.
|
||
; SHOULD BE FIXED WHEN DRIVER REVVED
|
||
;@ResetSCC
|
||
dc.b $A9,$30 ; lda #$30 send err reset to SCC
|
||
dc.b $8D,$41,$F0 ; sta SCC_Ctl
|
||
dc.b $AD,$43,$F0 ; lda SCC_Data flush SCC FIFO
|
||
dc.b $A9,$30 ; lda #$30 send err reset to SCC
|
||
dc.b $8D,$41,$F0 ; sta SCC_Ctl
|
||
dc.b $AD,$43,$F0 ; lda SCC_Data flush SCC FIFO
|
||
dc.b $A9,$30 ; lda #$30 send err reset to SCC
|
||
dc.b $8D,$41,$F0 ; sta SCC_Ctl
|
||
;@Done
|
||
dc.b $4C,$b0,$2E ; jump back to our regularly scheduled code $2d55(base) +$15b(offset)
|
||
|
||
; fixes ctrl calls to wait for all sent from SCC before executing
|
||
@a9end dc.b $08,$C6 ; offset to this patch
|
||
dc.b @a10end-@a10 ; number patchbytes
|
||
|
||
;@wait_more <37>
|
||
@a10 dc.b $78 ; sei turn off interrupts <37>
|
||
dc.b $A9,$01 ; lda #$01 read RR1 <37>
|
||
dc.b $8D,$41,$F0 ; sta SCC_Ctl <37>
|
||
dc.b $AD,$41,$F0 ; lda SCC_Ctl <37>
|
||
dc.b $58 ; cli turn on interrupts <37>
|
||
dc.b $6A ; ror a test the all sent bit, bit 0 <37>
|
||
dc.b $90,$F3 ; bcc @wait_more <37>
|
||
dc.b $7C,$33,$35 ; jmp (ControlDispatch,x) <37>
|
||
; ControlDispatch at $3533 = $2d55(base) + $7DE(offset) <37>
|
||
|
||
; fixes ctrl calls to wait for all sent from SCC before executing <37>
|
||
@a10end dc.b $08,$D6 ; offset to this patch <37>
|
||
dc.b @a11end-@a11 ; number patchbytes <37>
|
||
; <37>
|
||
; ctsFlag = 0 on input. Acc holds RRO value <37>
|
||
@a11 dc.b $29,$A0 ; and #$A0 isolate DTR and break bits <37>
|
||
dc.b $85,$58 ; sta holdRR0 $55(base) + $17(offset) <37>
|
||
dc.b $29,$20 ; and #$20 is DTR asserted? <37>
|
||
dc.b $F0,$02 ; beq @1 yes, then CTSFlag stays 0 <37>
|
||
dc.b $C6,$6C ; dec CTSFlag no, then CTSFlag goes to $FF CTSFlag at $55(base) + $17(offset)
|
||
dc.b $4C,$59,$2E ;@1 jmp backToCode at $2e59 = $2d55(base) + $104 offset <37>
|
||
|
||
; adds external clocking control into bit 6 of the
|
||
; CtlOptions byte for control call 16
|
||
@a11end dc.b $08,$e3 ; offset to this patch
|
||
dc.b @a13end-@a13 ; number of patchbytes
|
||
|
||
@a13 dc.b $a5,$73 ;lda CtlOptions get old clk bit $55(base)+$1e(offset)
|
||
dc.b $29,$40 ;and #clkMsk bit 6
|
||
dc.b $aa ;tax
|
||
dc.b $ad,$84,$02 ;lda C16_CtlOptions get new byte $200(base)+$80(msg#)+$4(offset)
|
||
dc.b $a8 ;tay
|
||
dc.b $29,$40 ;and #clkMsk bit 6
|
||
dc.b $85,$73 ;sta CtlOptions $55(base)+$1e(offset)
|
||
dc.b $8a ;txa
|
||
dc.b $c5,$73 ;cmp CtlOptions is old clock bit same as new? $55(base)+$1e(offset)
|
||
dc.b $d0,$05 ;bne @switchIt nope, switch clk mode
|
||
dc.b $84,$73 ;@out sty CtlOptions store new byte $55(base)+$1e(offset)
|
||
dc.b $4c,$7f,$30 ;jmp DoControlEvent_Return $2d55(base) +$32a(offset)
|
||
|
||
dc.b $98 ;@switchIt tya
|
||
dc.b $0a ;asl shift into minus bit
|
||
dc.b $30,$14 ;bmi @ext
|
||
|
||
dc.b $a9,$50 ;@int lda #intClkSrc set int clk params
|
||
dc.b $8d,$17,$35 ;sta WR11_Data $2d55(base) +$7c2(offset)
|
||
dc.b $a9,$01 ;lda #BRGEnbl
|
||
dc.b $8d,$1d,$35 ;sta WR14_Data $2d55(base) +$7c8(offset)
|
||
dc.b $ad,$0d,$35 ;lda WR4_data set clock divide to 16 $2d55(base) +$7b8(offset)
|
||
dc.b $09,$40 ;ora #dvd16Msk clock divide bit is bit 6
|
||
dc.b $8d,$0d,$35 ;sta WR4_data in WR4 $2d55(base) +$7b8(offset)
|
||
dc.b $80,$12 ;bra @load
|
||
|
||
dc.b $a9,$28 ;@ext lda #extClkSrc set ext clk params
|
||
dc.b $8d,$17,$35 ;sta WR11_Data $2d55(base) +$7c2(offset)
|
||
dc.b $a9,$00 ;lda #BRGDsbl
|
||
dc.b $8d,$1d,$35 ;sta WR14_Data $2d55(base) +$7c8(offset)
|
||
dc.b $ad,$0d,$35 ;lda WR4_data set clock divide to one $2d55(base) +$7b8(offset)
|
||
dc.b $29,$BF ;and #dvdOneMsk clock divide bit is bit 6
|
||
dc.b $8d,$0d,$35 ;sta WR4_data in WR4 $2d55(base) +$7b8(offset)
|
||
|
||
dc.b $5a ;@load phy ; save the control byte
|
||
dc.b $64,$63 ;stz HWHSenable disable hardware handshaking $55(base)+$0e(offset) <126>
|
||
dc.b $20,$f4,$34 ;jsr DoInitSCC $2d55(base) +$79f(offset)
|
||
dc.b $7a ;ply
|
||
dc.b $80,$c8 ;bra @out <126>
|
||
|
||
; patch to set bit 3 of AsyncErr if break received
|
||
@a13end dc.b $09,$2d ; offset to this patch <126>
|
||
dc.b @a15end-@a15 ; number of patchbytes
|
||
|
||
@a15 dc.b $8a ;txa a=changed bits
|
||
dc.b $30,$03 ;bmi @change break changed
|
||
dc.b $4c,$ad,$34 ;@done jmp ExtStatEnd $2d55(base) +$758(offset)
|
||
dc.b $a5,$58 ;@change lda LastRRO get break value $55(base)+$03(offset)
|
||
dc.b $30,$05 ;bmi @post break was set
|
||
dc.b $ad,$43,$f0 ;lda SCC_data break unset, discard null
|
||
dc.b $80,$f4 ;bra @done
|
||
dc.b $a9,$08 ;@post lda #$08 set bit 3
|
||
dc.b $24,$67 ;bit ResetAsyncErr has host read stats $55(base)+$12(offset)
|
||
dc.b $10,$04 ;bpl @unread
|
||
dc.b $64,$68 ;stz AsyncErr $55(base)+$13(offset)
|
||
dc.b $64,$67 ;stz ResetAsyncErr $55(base)+$12(offset)
|
||
dc.b $05,$68 ;@unread ora AsyncErr $55(base)+$13(offset)
|
||
dc.b $85,$68 ;sta AsyncErr $55(base)+$13(offset)
|
||
dc.b $80,$e4 ;bra @done
|
||
|
||
; patch to set clock divide bits for WR4 and disable HWHS for ext clock
|
||
@a15end dc.b $09,$4c ; offset to this patch <126>
|
||
dc.b @a17end-@a17 ; number of patchbytes
|
||
|
||
;acc=%0400xxxx default to divide-by-16
|
||
@a17 dc.b $da ;phx save reg
|
||
dc.b $aa ;tax save acc
|
||
dc.b $a5,$73 ;lda CtlOptions are we ext clk'd? $55(base)+$1e(offset)
|
||
dc.b $0a ;asl shift ext clk bit into minus bit
|
||
dc.b $30,$03 ;bmi @ext yes, go fix clk dvd bits and disable HWHS
|
||
dc.b $8a ;@int txa no, just restore acc
|
||
dc.b $80,$03 ;bra @done <126>
|
||
dc.b $8a ;@ext txa restore acc
|
||
dc.b $29,$0f ;and #$0f fix clk dvd bits to div-by-one
|
||
; dc.b $64,$63 ;stz HWHSenable disable hardware handshaking $55(base)+$0e(offset)<126>
|
||
dc.b $fa ;@done plx restore reg
|
||
dc.b $8d,$0d,$35 ;sta WR4_Data and write out WR4 value $2d55(base) +$7b8(offset)
|
||
dc.b $4c,$d1,$34 ;jmp FinishInitSCC and finish up $2d55(base) +$77c(offset)
|
||
|
||
; patch to disable CTS interrupts if we get them too fast
|
||
@a17end dc.b $09,$60 ; offset to this patch
|
||
dc.b @a19end-@a19 ; number of patchbytes
|
||
|
||
@a19 dc.b $a5,$88 ;lda CTSCount exceeded 5 transitions in 1 ms? $55(base)+$33(offset)
|
||
dc.b $c9,$05 ;cmp #5
|
||
dc.b $90,$0c ;bcc @fixTime no, then fix the time
|
||
|
||
dc.b $a9,$0f ;lda #15 yes, then disable CTS interrupts
|
||
dc.b $8d,$41,$f0 ;sta SCC_Ctl write to WR15
|
||
dc.b $a9,$80 ;lda #$80 bit 5 clear to disable CTS ints
|
||
dc.b $8d,$41,$f0 ;sta SCC_Ctl
|
||
|
||
dc.b $80,$12 ;bra @out go finish in ROM
|
||
|
||
;@fixTime
|
||
dc.b $a5,$89 ;lda LastTime get last count (remember it's a countdown timer)
|
||
dc.b $ed,$11,$f0 ;sbc TimerCounterH time elasped > threshold? $55(base)+$34(offset)
|
||
dc.b $c9,$08 ;cmp #threshold threshold is 1 msÅ 8 ticks
|
||
dc.b $90,$07 ;bcc @update no, just increment <138>
|
||
|
||
dc.b $ad,$11,$f0 ;lda TimerCounterH yes, set new last time
|
||
dc.b $85,$89 ;sta LastTime $55(base)+$34(offset)
|
||
dc.b $64,$88 ;stz CTSCount and restart count $55(base)+$33(offset)
|
||
|
||
;@update inc the transition count
|
||
dc.b $e6,$88 ;inc CTSCount $55(base)+$33(offset)
|
||
|
||
;@out
|
||
dc.b $64,$6c ;stz CTSFlag do stuff we stomped on in overpatch $55(base)+$17(offset)
|
||
dc.b $a5,$58 ;lda RRO $55(base)+$03(offset)
|
||
dc.b $4c,$8f,$34 ;jmp BackToROM finish up in ROM $2d55(base) +$73a(offset)
|
||
|
||
; patch to close to time-out on the all sent loop
|
||
@a19end dc.b $09,$8b ; offset to this patch
|
||
dc.b @a22end-@a22 ; number of patchbytes
|
||
|
||
@a22 dc.b $a5,$FF ;ldx #$FF load up $FFFF for timeout loop
|
||
dc.b $c9,$FF ;ldy #$FF 24 cycles * .5 us/cycle * 64K Å .8 seconds
|
||
|
||
dc.b $a9,$01 ;@loop lda #1 read from RR1
|
||
dc.b $8d,$41,$f0 ;sta SCC_Ctl
|
||
dc.b $ad,$41,$f0 ;lda SCC_Ctl
|
||
dc.b $6a ;ror get all sent bit in carry
|
||
dc.b $b0,$06 ;bcs @done if allsent, then outta here
|
||
|
||
dc.b $ca ;dex not allsent, so keep waiting
|
||
dc.b $d0,$f2 ;bne @loop
|
||
dc.b $88 ;dey
|
||
dc.b $d0,$ef ;bne @loop
|
||
dc.b $4c,$cf,$2f ;@done jumpBacktoClose $2d55(base) +$27a(offset)
|
||
|
||
; patch to start the IOP timer
|
||
@a22end dc.b $09,$a3 ; offset to this patch
|
||
dc.b @a24end-@a24 ; number of patchbytes
|
||
|
||
@a24 dc.b $9c,$24,$f0 ;stz DMA_CntHi do code we stomped with patch
|
||
dc.b $a9,$ff ;lda #$FF
|
||
dc.b $8d,$11,$f0 ;sta TimerCounterH get the timer started (just need to write to it)
|
||
dc.b $4c,$f0,$2d ;@done jumpBacktoOpen $2d55(base) +$09b(offset)
|
||
|
||
|
||
@a24end dc.w 0 ; filler
|
||
|
||
|
||
DrvrBFix
|
||
|
||
|
||
; changes zero page init to clear all $55 bytes
|
||
; this one-byte change is inline.
|
||
dc.b $00,$09 ; offset to this patch
|
||
dc.b @b20end-@b20 ; number patchbytes
|
||
|
||
@b20 dc.b $55 ; y<-$55, the index to clear out z-page
|
||
|
||
; fixes the new location of the driver buffers
|
||
; new buffer start addr is $604d = $56aa(base) + $9a3(new offset)
|
||
@b20end dc.b $00,$46 ; offset to this patch
|
||
dc.b @b1end-@b1 ; number patchbytes
|
||
|
||
@b1 dc.b $a9,$60 ; lda #>Buffers (new high byte)
|
||
dc.b $a2,$4d ; lda #>Buffers (new low byte)
|
||
|
||
; fix one byte to load into DMA count
|
||
@b1end dc.b $00,$94 ; offset to this patch
|
||
dc.b @b2end-@b2 ; number patchbytes
|
||
|
||
@b2 dc.b $FB ; put FB in the DMA count instead of FF
|
||
|
||
; calls the fix to start the IOP timer since
|
||
; patch wouldn't fit inline
|
||
@b2end dc.b $00,$98 ; offset to this patch <138>
|
||
dc.b @b23end-@b23 ; number patchbytes <138>
|
||
; <138>
|
||
@b23 dc.b $4C,$4d,$60 ; jmp to fix at addr $604d = $56aa(base) +$9a3(offset) <138>
|
||
|
||
; calls the fix to CTSFlag on Open (see patch at $8D5) since the
|
||
; patch wouldn't fit inline
|
||
@b23end dc.b $01,$00 ; offset to this patch <37>
|
||
dc.b @b3end-@b3 ; number patchbytes <37>
|
||
; <37>
|
||
@b3 dc.b $4c,$80,$5F ; jmp to fix at addr $5F80 = $56aa(base) +$8D6(offset) <37>
|
||
|
||
; calls the fix to DoPollEvent (see patch at $880) since the
|
||
; patch wouldn't fit inline
|
||
@b3end dc.b $01,$2F ; offset to this patch
|
||
dc.b @b4end-@b4 ; number patchbytes
|
||
|
||
@b4 dc.b $20,$2a,$5F ; jsr to fix at address $56aa(base) +$880(offset)
|
||
|
||
; calls the fix to DMA code (see patch at 886) since the
|
||
; patch wouldn't fit inline
|
||
@b4end dc.b $01,$46 ; offset to this patch
|
||
dc.b @b5end-@b5 ; number patchbytes
|
||
|
||
@b5 dc.b $F0,$03 ; beq to just below
|
||
dc.b $4C,$30,$5F ; jmp here if DMA was NOT stopped by interrupt rtn $56aa(base)+$886(offset)
|
||
dc.b $4C,$57,$5F ; jmp here if DMA was stopped by interrupt rtn $56aa(base)+$8ad(offset)
|
||
|
||
; fix one byte to load into DMA count
|
||
@b5end dc.b $01,$6E ; offset to this patch
|
||
dc.b @b6end-@b6 ; number patchbytes
|
||
|
||
@b6 dc.b $FB ; put FB in the DMA count instead of FF
|
||
|
||
; calls patch to close to time-out on the all sent loop since the
|
||
; patch wouldn't fit inline
|
||
@b6end dc.b $02,$6F ; offset to this patch
|
||
dc.b @b21end-@b21 ; number patchbytes
|
||
|
||
@b21 dc.b $4C,$35,$60 ; jmp to fix at address $6035 = $56aa(base) +$98b(offset) <37>
|
||
|
||
; calls the fix to all sent in control calls (see patch at 8C6) since the <37>
|
||
; patch wouldn't fit inline <37>
|
||
@b21end dc.b $03,$39 ; offset to this patch <37>
|
||
dc.b @b7end-@b7 ; number patchbytes <37>
|
||
; <37>
|
||
@b7 dc.b $4C,$70,$5F ; jmp to fix at address $5F70 = $56aa(base) +$8C6(offset) <37>
|
||
|
||
; calls patch to add ext clking to control call 16 since the
|
||
; patch wouldn't fit inline
|
||
@b7end dc.b $4,$4a ; offset to this patch
|
||
dc.b @b12end-@b12
|
||
|
||
@b12 dc.b $4c,$8d,$5f ; jump to fix at address $5f8d= $56aa(base) + $8e3(offset)
|
||
|
||
; calls patch to disable CTS interrupts if we get them too fast since
|
||
; patch wouldn't fit inline
|
||
@b12end dc.b $07,$36 ; offset to this patch
|
||
dc.b @b18end-@b18
|
||
|
||
@b18 dc.b $4c,$0a,$60 ; jump to fix at address $600a= $56aa(base) + $960(offset)
|
||
|
||
; calls patch to set bit 3 of AsyncErr if break received since
|
||
; patch wouldn't fit inline
|
||
@b18end dc.b $07,$55 ; offset to this patch
|
||
dc.b @b14end-@b14
|
||
|
||
@b14 dc.b $4c,$d7,$5f ; jump to fix at address $5fd7= $56aa(base) + $92d(offset)
|
||
|
||
; calls patch to set clock divide bits for WR4 since
|
||
; patch wouldn't fit inline
|
||
@b14end dc.b $07,$79 ; offset to this patch
|
||
dc.b @b16end-@b16
|
||
|
||
@b16 dc.b $4c,$f6,$5f ; jump to fix at address $5ff6= $56aa(base) + $94c(offset)
|
||
|
||
; fixes the code at DoPollEvent to compare to DMA count,
|
||
; not the DMA address.
|
||
@b16end dc.b $08,$80 ; offset to this patch
|
||
dc.b @b8end-@b8 ; number patchbytes
|
||
|
||
|
||
@b8 dc.b $AD,$2B,$F0 ; lda DMACntLo
|
||
dc.b $C9,$FB ; cmp #$FB
|
||
dc.b $60 ; rts
|
||
|
||
; fixes DMA code to check for bytes left over in the SCC fifo
|
||
@b8end dc.b $08,$86 ; offset to this patch
|
||
dc.b @b9end-@b9 ; number patchbytes
|
||
|
||
@b9 dc.b $AD,$2A,$F0 ; lda DMA_AddrHi Set up temp pointer
|
||
dc.b $85,$AF ; sta TempBufPtr+1 into the DMA buffer. $aa(base)+$05(offset)
|
||
dc.b $64,$AE ; stz TempBufPtr $aa(base)+$04(offset)
|
||
dc.b $AC,$29,$F0 ; ldy DMA_AddrLo Get the byte offset into buffer
|
||
;@NxtChar
|
||
dc.b $AD,$40,$F0 ; lda SCC_Ctl Read RRO
|
||
dc.b $29,$01 ; and #Rx_CharAvail is there a receive char?
|
||
dc.b $F0,$2B ; beq @Done no chars, then we are done
|
||
dc.b $AD,$42,$F0 ; lda SCC_Data get the data char
|
||
dc.b $91,$AE ; sta (TempBufPtr),y store char in buffer $aa(base)+$04(offset)
|
||
dc.b $84,$D4 ; Sty HoldDMACount $aa(base)+$2a(offset)
|
||
dc.b $C8 ; iny
|
||
; if any errors reset the scc
|
||
dc.b $A9,$01 ; lda #1 read RR1
|
||
dc.b $8D,$40,$F0 ; sta SCC_Ctl
|
||
dc.b $AD,$40,$F0 ; lda SCC_Ctl
|
||
dc.b $29,$70 ; and #$70 parity, overrun, framing err?
|
||
dc.b $85,$B3 ; sta HoldRR1 save errors $aa(base)+$09(offset)
|
||
dc.b $F0,$E3 ; beq @NxtChar no get the next char
|
||
; Suppose Special Rx Int has turned off DMA.
|
||
; There could be chars in FIFO after interrupt.
|
||
; Driver only flags errors on last byte DMAd in.
|
||
; To insure this, drop all bytes after error.
|
||
; SHOULD BE FIXED WHEN DRIVER REVVED
|
||
;@ResetSCC
|
||
dc.b $A9,$30 ; lda #$30 send err reset to SCC
|
||
dc.b $8D,$40,$F0 ; sta SCC_Ctl
|
||
dc.b $AD,$42,$F0 ; lda SCC_Data flush SCC FIFO
|
||
dc.b $A9,$30 ; lda #$30 send err reset to SCC
|
||
dc.b $8D,$40,$F0 ; sta SCC_Ctl
|
||
dc.b $AD,$42,$F0 ; lda SCC_Data flush SCC FIFO
|
||
dc.b $A9,$30 ; lda #$30 send err reset to SCC
|
||
dc.b $8D,$40,$F0 ; sta SCC_Ctl
|
||
;@Done
|
||
dc.b $4C,$05,$58 ; jump back to our regularly scheduled code $56aa(base) +$15B(offset)
|
||
|
||
; fixes ctrl calls to wait for all sent from SCC before executing <37>
|
||
@b9end dc.b $08,$C6 ; offset to this patch <37>
|
||
dc.b @b10end-@b10 ; number patchbytes <37>
|
||
; <37>
|
||
;@wait_more <37>
|
||
@b10 dc.b $78 ; sei turn off interrupts <37>
|
||
dc.b $A9,$01 ; lda #$01 read RR1 <37>
|
||
dc.b $8D,$40,$F0 ; sta SCC_Ctl <37>
|
||
dc.b $AD,$40,$F0 ; lda SCC_Ctl <37>
|
||
dc.b $58 ; cli turn on interrupts <37>
|
||
dc.b $6A ; ror a test the all sent bit, bit 0 <37>
|
||
dc.b $90,$F3 ; bcc @wait_more <37>
|
||
dc.b $7C,$88,$5E ; jmp (ControlDispatch,x) <37>
|
||
; ControlDispatch at $5E88 = $56aa(base) + $7DE(offset) <37>
|
||
|
||
; fixes ctrl calls to wait for all sent from SCC before executing <37>
|
||
@b10end dc.b $08,$D6 ; offset to this patch <37>
|
||
dc.b @b11end-@b11 ; number patchbytes <37>
|
||
; <37>
|
||
; ctsFlag = 0 on input. Acc holds RRO value <37>
|
||
@b11 dc.b $29,$A0 ; and #$A0 isolate DTR and break bits <37>
|
||
dc.b $85,$AD ; sta holdRR0 $aa(base) + $17(offset) <37>
|
||
dc.b $29,$20 ; and #$20 is DTR asserted? <37>
|
||
dc.b $F0,$02 ; beq @1 yes, then CTSFlag stays 0 <37>
|
||
dc.b $C6,$C1 ; dec CTSFlag no, then CTSFlag goes to $FF CTSFlag at $aa(base) + $17(offset)
|
||
dc.b $4C,$AE,$57 ;@1 jmp backToCode at $57AE = $56aa(base) + $104 offset <37>
|
||
|
||
; adds external clocking control into bit 6 of the
|
||
; CtlOptions byte for control call 16
|
||
@b11end dc.b $08,$e3 ; offset to this patch
|
||
dc.b @b13end-@b13 ; number of patchbytes
|
||
|
||
@b13 dc.b $a5,$c8 ;lda CtlOptions get old clk bit $aa(base)+$1e(offset)
|
||
dc.b $29,$40 ;and #clkMsk bit 6
|
||
dc.b $aa ;tax
|
||
dc.b $ad,$e4,$02 ;lda C16_CtlOptions get new byte $200(base)+$e0(msg#)+$04
|
||
dc.b $a8 ;tay
|
||
dc.b $29,$40 ;and #clkMsk bit 6
|
||
dc.b $85,$c8 ;sta CtlOptions $aa(base)+$1e(offset)
|
||
dc.b $8a ;txa
|
||
dc.b $c5,$c8 ;cmp CtlOptions is old clock bit same as new? $aa(base)+$1e(offset)
|
||
dc.b $d0,$05 ;bne @switchIt nope, switch clk mode
|
||
dc.b $84,$c8 ;@out sty CtlOptions store new byte $aa(base)+$1e(offset)
|
||
dc.b $4c,$d4,$59 ;jmp DoControlEvent_Return $56aa(base) +$32a(offset)
|
||
|
||
dc.b $98 ;@switchIt tya
|
||
dc.b $0a ;asl shift into minus bit
|
||
dc.b $30,$14 ;bmi @ext
|
||
|
||
dc.b $a9,$50 ;@int lda #intClkSrc set int clk params
|
||
dc.b $8d,$6c,$5e ;sta WR11_Data $56aa(base) +$7c2(offset)
|
||
dc.b $a9,$01 ;lda #BRGEnbl
|
||
dc.b $8d,$72,$5e ;sta WR14_Data $56aa(base) +$7c8(offset)
|
||
dc.b $ad,$62,$5e ;lda WR4_data set clock divide to 16 $56aa(base) +$7b8(offset)
|
||
dc.b $09,$40 ;ora #dvd16Msk clock divide bit is bit 6
|
||
dc.b $8d,$62,$5e ;sta WR4_data in WR4 $56aa(base) +$7b8(offset)
|
||
dc.b $80,$12 ;bra @load
|
||
|
||
dc.b $a9,$28 ;@ext lda #extClkSrc set ext clk params
|
||
dc.b $8d,$6c,$5e ;sta WR11_Data $56aa(base) +$7c2(offset)
|
||
dc.b $a9,$00 ;lda #BRGDsbl
|
||
dc.b $8d,$72,$5e ;sta WR14_Data $56aa(base) +$7c8(offset)
|
||
dc.b $ad,$62,$5e ;lda WR4_data set clock divide to one $56aa(base) +$7b8(offset)
|
||
dc.b $29,$BF ;and #dvdOneMsk clock divide bit is bit 6
|
||
dc.b $8d,$62,$5e ;sta WR4_data in WR4 $56aa(base) +$7b8(offset)
|
||
|
||
dc.b $5a ;@load phy ; save the control byte
|
||
dc.b $64,$b8 ;stz HWHSenable disable hardware handshaking $aa(base)+$0e(offset)
|
||
dc.b $20,$49,$5e ;jsr DoInitSCC $56aa(base) +$79f(offset)
|
||
dc.b $7a ;ply
|
||
dc.b $80,$c8 ;bra @out
|
||
|
||
; patch to set bit 3 of AsyncErr if break received
|
||
@b13end dc.b $09,$2d ; offset to this patch
|
||
dc.b @b15end-@b15 ; number of patchbytes
|
||
|
||
@b15 dc.b $8a ;txa a=changed bits
|
||
dc.b $30,$03 ;bmi @change break changed
|
||
dc.b $4c,$02,$5e ;@done jmp ExtStatEnd $56aa(base) +$758(offset)
|
||
dc.b $a5,$ad ;@change lda LastRRO get break value $aa(base)+$03(offset)
|
||
dc.b $30,$05 ;bmi @post break was set
|
||
dc.b $ad,$42,$f0 ;lda SCC_Data break unset, discard null
|
||
dc.b $80,$f4 ;bra @done
|
||
dc.b $a9,$08 ;@post lda #$08 set bit 3
|
||
dc.b $24,$bc ;bit ResetAsyncErr has host read stats $aa(base)+$12(offset)
|
||
dc.b $10,$04 ;bpl @unread
|
||
dc.b $64,$bd ;stz AsyncErr $aa(base)+$13(offset)
|
||
dc.b $64,$bc ;stz ResetAsyncErr $aa(base)+$12(offset)
|
||
dc.b $05,$bd ;@unread ora AsyncErr $aa(base)+$13(offset)
|
||
dc.b $85,$bd ;sta AsyncErr $aa(base)+$13(offset)
|
||
dc.b $80,$e4 ;bra @done
|
||
|
||
; patch to set clock divide bits for WR4 and disable HWHS for external clocking
|
||
@b15end dc.b $09,$4c ; offset to this patch
|
||
dc.b @b17end-@b17 ; number of patchbytes
|
||
|
||
;acc=%0400xxxx default to divide-by-16
|
||
@b17 dc.b $da ;phx save reg
|
||
dc.b $aa ;tax save acc
|
||
dc.b $a5,$c8 ;lda CtlOptions are we ext clk'd? $aa(base)+$1e(offset)
|
||
dc.b $0a ;asl shift ext clk bit into minus bit
|
||
dc.b $30,$03 ;bmi @ext yes, go fix clk dvd bits
|
||
dc.b $8a ;@int txa no, just restore acc
|
||
dc.b $80,$03 ;bra @done
|
||
dc.b $8a ;@ext txa restore acc
|
||
dc.b $29,$0f ;and #$0f fix clk dvd bits to div-by-one
|
||
; dc.b $64,$b8 ;stz HWHSenable disable hardware handshaking $aa(base)+$0e(offset)
|
||
dc.b $fa ;@done plx restore reg
|
||
dc.b $8d,$62,$5e ;sta WR4_Data and write out WR4 value $56aa(base) +$7b8(offset)
|
||
dc.b $4c,$26,$5e ;jmp FinishInitSCC and finish up $56aa(base) +$77c(offset)
|
||
|
||
|
||
; patch to disable CTS interrupts if we get them too fast
|
||
@b17end dc.b $09,$60 ; offset to this patch
|
||
dc.b @b19end-@b19 ; number of patchbytes
|
||
|
||
@b19 dc.b $a5,$dd ;lda CTSCount exceeded 5 transitions in 1 ms? $aa(base)+$33(offset)
|
||
dc.b $c9,$05 ;cmp #5
|
||
dc.b $90,$0c ;bcc @fixTime no, then fix the time
|
||
|
||
dc.b $a9,$0f ;lda #15 yes, then disable CTS interrupts
|
||
dc.b $8d,$40,$f0 ;sta SCC_Ctl write to WR15
|
||
dc.b $a9,$80 ;lda #$80 bit 5 clear to disable CTS ints
|
||
dc.b $8d,$40,$f0 ;sta SCC_Ctl
|
||
|
||
dc.b $80,$12 ;bra @out go finish in ROM
|
||
|
||
;@fixTime
|
||
dc.b $a5,$de ;lda LastTime get last count (remember it's a countdown timer) $aa(base)+$34(offset)
|
||
dc.b $ed,$11,$f0 ;sbc TimerCounterH time elasped > threshold?
|
||
dc.b $c9,$08 ;cmp #threshold threshold is 1 msÅ 8 ticks
|
||
dc.b $90,$07 ;bcc @update no, just increment <138>
|
||
|
||
dc.b $ad,$11,$f0 ;lda TimerCounterH yes, set new last time
|
||
dc.b $85,$de ;sta LastTime $aa(base)+$34(offset)
|
||
dc.b $64,$dd ;stz CTSCount and restart count $aa(base)+$33(offset)
|
||
|
||
;@update inc the transition count
|
||
dc.b $e6,$dd ;inc CTSCount $aa(base)+$33(offset)
|
||
|
||
;@out
|
||
dc.b $64,$c1 ;stz CTSFlag do stuff we stomped on in overpatch $aa(base)+$17(offset)
|
||
dc.b $a5,$ad ;lda RRO $aa(base)+$03(offset)
|
||
dc.b $4c,$e4,$5d ;jmp BackToROM finish up in ROM $56aa(base) +$73a(offset)
|
||
|
||
; patch to close to time-out on the all sent loop
|
||
@b19end dc.b $09,$8b ; offset to this patch
|
||
dc.b @b22end-@b22 ; number of patchbytes
|
||
|
||
@b22 dc.b $a5,$FF ;ldx #$FF load up $FFFF for timeout loop
|
||
dc.b $c9,$FF ;ldy #$FF 24 cycles * .5 us/cycle * 64K Å .8 seconds
|
||
|
||
dc.b $a9,$01 ;@loop lda #1 read from RR1
|
||
dc.b $8d,$40,$f0 ;sta SCC_Ctl
|
||
dc.b $ad,$40,$f0 ;lda SCC_Ctl
|
||
dc.b $6a ;ror get all sent bit in carry
|
||
dc.b $b0,$06 ;bcs @done if allsent, then outta here
|
||
|
||
dc.b $ca ;dex not allsent, so keep waiting
|
||
dc.b $d0,$f2 ;bne @loop
|
||
dc.b $88 ;dey
|
||
dc.b $d0,$ef ;bne @loop
|
||
dc.b $4c,$24,$59 ;@done jumpBacktoClose $56aa(base) +$27a(offset)
|
||
|
||
|
||
; patch to start the IOP timer
|
||
@b22end dc.b $09,$a3 ; offset to this patch
|
||
dc.b @b24end-@b24 ; number of patchbytes
|
||
|
||
@b24 dc.b $9c,$2c,$f0 ;stz DMA_CntHi do code we stomped with patch
|
||
dc.b $a9,$ff ;lda #$FF
|
||
dc.b $8d,$11,$f0 ;sta TimerCounterH get the timer started (just need to write to it)
|
||
dc.b $4c,$45,$57 ;@done jumpBacktoOpen $56aa(base) +$09b(offset)
|
||
|
||
|
||
@b24end dc.w 0 ; filler
|
||
|
||
;_______________________________________________________________________
|
||
;
|
||
; Routine: IOPMoveData
|
||
; Inputs: A0 - pointer to IOPMoveInfo paramater block
|
||
; Outputs: D0 - Result Code (NoErr/paramErr)
|
||
; Destroys: A0, A1, D0, D1, D2
|
||
; Calls: CopyToIOP, CopyFromIOP, CompareWithIop
|
||
; Called by: OsTrap Dispatch Table
|
||
;
|
||
; Function: Moves, or compares data between the IOP and the Host
|
||
; memories, using the parameters inthe IOPMoveInfo parameter
|
||
; block. Also has a special mode to apply patches to IOP
|
||
; memory as an atomic operation.
|
||
;
|
||
;_______________________________________________________________________
|
||
|
||
with IOPMoveInfo
|
||
IOPMoveData
|
||
|
||
; We can use the new protection scheme, if the first two instructions in the <115>
|
||
; patch are a bra.s followed by the jump to the old rom address.
|
||
|
||
bra.s @protection
|
||
@NoPatch
|
||
BackToTrap oldIOPMoveData ; no, then just execute ROM Code
|
||
@protection
|
||
|
||
|
||
; are we coming from the IOP serial driver open call?
|
||
cmpRA From_IOPOpenCall,OSTrapReturnAddressDepth(sp)
|
||
bne.s @NoPatch
|
||
|
||
|
||
|
||
@chkA lea DrvrAFix,a1 ; get address of our patchbytes
|
||
cmpi.w #DrvrAPicAddr,imIOPAddr(a0)
|
||
beq.s @doPatch
|
||
@chkB lea DrvrBFix,a1 ; get address of our patchbytes
|
||
cmpi.w #DrvrBPicAddr,imIOPAddr(a0)
|
||
bne.s @noPatch ; not our drivers? well, don't patch then
|
||
|
||
@doPatch
|
||
; Call the ROM to download the unpatched image
|
||
_IOPMoveData
|
||
|
||
; now patch the downloaded driver. Each section of patch bytes
|
||
; is preceded by an offset word and a count byte.
|
||
; a2 has start addr of our patch bytes.
|
||
|
||
moveq #numpatches-1,d1 ; number of patches (minus 1 for dbra)
|
||
move.w imIOPAddr(a0),d2 ; get base addr of downloaded driver
|
||
moveq #0,d0 ; for additions
|
||
move.w d0,imByteCount(a0) ; clear out high byte of count
|
||
@patchloop
|
||
move.w d2,d0 ; get base addr of downloaded driver
|
||
add.w (a1)+,d0 ; add in offset to patch start
|
||
move.w d0,imIOPAddr(a0) ; set dest addr for patchbytes
|
||
move.b (a1)+,imByteCount+1(a0) ; number patchbytes
|
||
move.l a1,imHostAddr(a0) ; set source addr of patchbytes
|
||
adda.w imByteCount(a0),a1 ; increment ptr past patchbytes
|
||
|
||
_IOPMoveData ; download the patch bytes
|
||
dbra d1,@patchloop ; go on to next patch
|
||
|
||
; note that when dbra expires, d0 will contain output for last IOPMove data
|
||
; performed, which is an approximation of what should be in d0
|
||
|
||
; note also that we've trashed the IOPMgr PB fields, but since the driver
|
||
; never refers to them again, and in the interest of STAYING SMALL, we'll
|
||
; ignore it.
|
||
rts
|
||
endwith
|
||
endproc
|
||
|
||
;
|
||
;
|
||
; End of Patch To IOPMoveData Trap to Fix IOP Serial Driver Control Call Bug
|
||
;____________________________________________________________________________ EH <33>
|
||
|
||
;____________________________________________________________________________
|
||
NewFLineRoutine PROC EXPORT
|
||
|
||
EXPORT OldFLineRoutine
|
||
|
||
cmp.w #$002C,6(sp) ;make sure that this is our stack frame. If not
|
||
bne.s OldFLineRoutine ;..then jump thru the old exception vector
|
||
|
||
MOVEM.L A0/D0,-(SP) ; Save these two registers <107>
|
||
|
||
move.l 8+2(sp),a0 ;get the address of the instruction word that caused
|
||
move.w (a0),d0 ;..this exception. Then copy the word into DO
|
||
and.w #%0000111000000000,d0 ;get just the co-processor ID from the instruction
|
||
cmp.w #%0000001000000000,d0 ;if itÕs not one, then it isnÕt a FPU instruction
|
||
bne.s stackError ;..so return thru the old FPU replacement routine
|
||
lea continue,a0 ;change the saved return address to our continuation
|
||
move.l a0,8+2(sp) ;..point and return out of exception mode.
|
||
|
||
MOVEM.L (SP)+,A0/D0 ; Restore the regs <107>
|
||
rte
|
||
|
||
continue move.w #dsNoFPU,d0 ;this displays the dialog that lets the user
|
||
_SysError ;..return to the finder (FPU type)
|
||
|
||
stackError MOVEM.L (SP)+,A0/D0 ; Restore the regs <107>
|
||
|
||
OldFLineRoutine JMP $12345678 ; This gets filled in at install time <107>
|
||
|
||
ENDP
|
||
;____________________________________________________________________________
|
||
|
||
|
||
|
||
;----------------------------------------------------------------------------------------------------
|
||
; This routine will read the Time LowMem global without
|
||
; issuing the call to Egret. Egret will keep the time updated
|
||
; in the background without needing system intervention. The
|
||
; Egret will post a unsolicited time packet which will update the
|
||
; LowMem global when it is not able to post the Tick packet
|
||
; within one second.
|
||
;----------------------------------------------------------------------------------------------------
|
||
|
||
RdDateTimePtch PROC EXPORT
|
||
|
||
move.l Time,(a0) ; return the time to the caller
|
||
clr.w d0 ; return no error <74>
|
||
rts
|
||
|
||
ENDP
|
||
|
||
;----------------------------------------------------------------------------------------------------
|
||
|
||
|
||
|
||
;----------------------------------------------------------------------------------------------------
|
||
; This patch fixes a bug in Egret Manager TickHandler routine. <89><101>
|
||
; The routine will store the 32 bit time passed by Egret to the
|
||
; system if the packet is a ReadRealTime into TIME lowmen.
|
||
; Decrements the lowmem Time by one to compensate for the interrupt
|
||
; Handler incrementing it by one and then calls the LVL1DT interrupt
|
||
; handler.
|
||
; If the packet is a tick packet then it calls LVL1DT to increment the
|
||
; time setting and check the alarm state.
|
||
;
|
||
; Entry:
|
||
; A1.l = Points at Response data buffer At Flags byte:
|
||
;
|
||
; +---------+----------+---------+---------+---------//-------+
|
||
; | Attn | Pkt Type | Flags | Pkt Cmd | 8 Bytes data Max |
|
||
; +---------+----------+---------+---------+---------//-------+
|
||
;
|
||
; A2.l = Points at Egret Manager Globals
|
||
;
|
||
;----------------------------------------------------------------------------------------------------
|
||
|
||
|
||
TickHandler PROC EXPORT
|
||
WITH respPacket,EgretGlobals
|
||
|
||
subq.l #2,a1 ; point to the beginning of the Response data buffer
|
||
cmpi.b #TickPkt,RespType(a1) ; Check the Packet type
|
||
beq.s @CallLVL1DT ; If tick packet just call LVL1DT handler
|
||
;
|
||
; The packet was a readTime packet from Egret. Update the Time lowmem and
|
||
; adjust it to compensate for the increment in the LVL1DT handler.
|
||
;
|
||
move.l RespData(a1),Time ; write the new time in lowmem TIME
|
||
subq.l #1,Time ; adjust to compensate for increment in LVL1DT
|
||
;
|
||
; JUMP to routine pointed to by the Contents of LVL1DT
|
||
;
|
||
|
||
@CallLVL1DT
|
||
move.l VIA,a1 ; point to the VIA
|
||
move.l LVL1DT,a0 ; get vector
|
||
jmp (a0)
|
||
|
||
|
||
ENDWITH
|
||
ENDP
|
||
|
||
;----------------------------------------------------------------------------------------------------
|
||
; This patch saves the processor status register, calls the <101> SAM
|
||
; ShiftRegIrq routine in Egret Manager and then restore the
|
||
; status register and exits.
|
||
;----------------------------------------------------------------------------------------------------
|
||
|
||
|
||
EgretIRQPtch PROC Export
|
||
EXPORT Vector_Hold
|
||
|
||
move.w sr,-(sp) ; save the status register
|
||
@IrqJmp jsr $10000000 ; this JSR will call the routine pointed to by the old
|
||
; contents of LVL1DT+8 vector (ShiftRegIrq)
|
||
move.w (sp)+,sr ; restore the status register
|
||
rts
|
||
|
||
Vector_hold equ @IrqJmp+2 ; point to the operand field
|
||
|
||
ENDP
|
||
|
||
|
||
;----------------------------------------------------------------------------------------------------
|
||
; This patch fixes possible loss of data to the SCC by calling <101> SAM
|
||
; the Poll Proc when SCC data is available.
|
||
;----------------------------------------------------------------------------------------------------
|
||
|
||
EgretDispatchPtch PROC Export
|
||
|
||
EMJmpAddr equ $14868 ; Offset added to Contents of Rombase for jmp back to Rom Egret Manager
|
||
; <104> removed declarations for Pollstack,PollProc, and HiIntMsk
|
||
with EgretPB, EgretGlobals
|
||
|
||
bsr CheckPacket ; Validate the Packet type & command byte
|
||
bne @done ; Exit if Error packet
|
||
movea.l EgretBase,a2 ; a2 gets ptr to globals
|
||
movea.l VIA,a1 ; a1 points to VIA base
|
||
|
||
cmpi.b #specialPkt,pbCmdType(a0) ; is this a special command?
|
||
bne.s @EgretRestart
|
||
|
||
move.l a0,ADBpb(a2) ; yes, is to set the ADB param block (for autopoll data).
|
||
bra @done
|
||
|
||
@EgretRestart
|
||
move.w sr,-(sp) ; save SR
|
||
ori.w #hiIntMask,sr ; mask interrupts
|
||
btst.b #xcvrSes,vBufB(a1) ; does Egret want to abort?
|
||
beq.s @abort ; yes, wait for it to go away
|
||
bset.b #busy,flags(a2) ; not an abort, mark that we're busy.
|
||
beq.s @sendPackType ; we were not busy before, so try to send the first byte
|
||
|
||
@abort move.w (sp)+,sr ; we were busy, enable interrupts
|
||
bsr pollByte ; poll shift reg, calling handler if interrupts masked
|
||
bra.s @EgretRestart ; and keep waiting for busy to go away...
|
||
|
||
@sendPackType ; interrupts masked here
|
||
bset.b #sysSes,vBufB(a1) ; assert System Session (we're starting command packet)
|
||
bset.b #SRdir,vACR(a1) ; switch to output
|
||
move.b pbCmdType(a0),vSR(a1) ; send command packet to shift reg
|
||
bset.b #viaFull,vBufB(a1) ; tell Egret we sent it
|
||
;_________________________
|
||
; If PollProc exists, Poll the SCC and save any available data
|
||
; When the shift register irq comes in call the PollProc
|
||
; then process the shift register irq data
|
||
;
|
||
movem.l d0/d1/a0-a4/a6,-(sp) ; save some registers
|
||
|
||
lea @zero, a3
|
||
move.l sp,PollStack ; Pointer to buffer for polled bytes
|
||
|
||
btst.b #0,SccIopFlag ; Check if we are in IOP mode (On Eclipse...)
|
||
beq.s @wait
|
||
|
||
tst.l PollProc ; Check for a Poll Proc available
|
||
beq.s @wait ;
|
||
|
||
movea.l SccRd,a3 ; SCC may have data to get
|
||
movea.l a3,a6
|
||
addq.l #Actl,a3 ; Point to data available register (RR0)
|
||
addq.l #AData,a6 ; Point to the SCC data register
|
||
|
||
|
||
@wait btst.b #RxCa,(a3) ; Test for SCC data available
|
||
beq.s @2
|
||
move.b (a6),-(sp) ; Push the data on the stack
|
||
@2 btst.b #vShift,vIFR(a1) ; now wait for shift reg IRQ
|
||
beq.s @wait
|
||
|
||
cmpa.l PollStack,SP ; Is there any poll data
|
||
beq.s @NoSCCData
|
||
;
|
||
; We have SCC data and a Poll Proc to call. Go call it
|
||
;
|
||
pea @NoSCCData ; Return addr for PollProc
|
||
move.l PollProc,-(SP) ; Point to the PollProc
|
||
rts ; Call the PollProc
|
||
|
||
@zero dc.w 0
|
||
|
||
|
||
@NoSCCData movem.l (sp)+,d0/d1/a0-a4/a6 ; restore work registers
|
||
|
||
@VsrIrq
|
||
btst.b #xcvrSes,vBufB(a1) ; did Egret abort?
|
||
bne.s @accepted ; no, then it will accept our packet
|
||
bclr.b #SRdir,vACR(a1) ; yes, switch back to input
|
||
bclr.b #sysSes,vBufB(a1) ; ack the abort
|
||
bsr.s CallShiftRegIRQ ; handle it
|
||
bra.s @abort ; and wait
|
||
|
||
@accepted
|
||
JmpROM EMJmpAddr ; Jump back into Rom Egret Manager <107>
|
||
|
||
@done moveq #0,d0 ; no errors for now
|
||
rts
|
||
|
||
;________________________________________________________________________________________________
|
||
CallShiftRegIRQ
|
||
movem.l a0-a3/d0-d3,-(sp) ; save regs like interrupt handler does
|
||
movea.l Lvl1DT+8,a0 ; get the shift reg IRQ handler
|
||
jsr (a0) ; call it
|
||
movem.l (sp)+,a0-a3/d0-d3 ; restore regs
|
||
rts
|
||
|
||
;________________________________________________________________________________________________
|
||
; Routine: PollByte
|
||
;
|
||
; Function: This routine checks to see if level 1 interrupts are masked, exits if not.
|
||
; If masked, it polls the flag register for a shift reg interrupt, and
|
||
; calls the handler if found.
|
||
;
|
||
; Inputs: a1 - VIA base ptr
|
||
; a2 - globals pointer
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Destroys: d0,d1
|
||
;________________________________________________________________________________________________
|
||
PollByte
|
||
move.w sr,d0 ; get 68xxx interrupt mask
|
||
andi.w #hiIntMask,d0 ; are we at interrupt level?
|
||
beq.s @exit ; no, just exit
|
||
btst.b #vShift,vIFR(a1) ; yes, poll the shift reg
|
||
beq.s @exit ; no shift reg interrupt, return
|
||
bsr.s CallShiftRegIRQ ; yes, handle it
|
||
@exit rts
|
||
|
||
;________________________________________________________________________________________________
|
||
;
|
||
; Validate the Packet type and Command if Pseudo Pkt.
|
||
;
|
||
; If an error is encountered with the packet a error packet will be
|
||
; built in the pbParam area of the parameter block as if Egret had
|
||
; returned the packet. Also, the pbResult field will contain a System
|
||
; error code for bad parameter block format.
|
||
;
|
||
; Entry: A0 = Parameter block pointer
|
||
;
|
||
; Exit: sr.Z = 0 if valid packet/pseudocmd nonzero otherwise
|
||
;
|
||
_________________________________________________________________________________________________
|
||
|
||
CheckPacket
|
||
cmp.b #SpecialPkt,pbCmdType(a0) ; could be an ADB initialization packet
|
||
beq.s @OkExit
|
||
|
||
cmp.b #ErrorPkt,pbCmdType(a0) ; ADB ($00) and Pseudo ($01) only
|
||
bhi.s @BadPkt ; Invalid packet
|
||
|
||
cmp.b #PseudoPkt,pbCmdType(a0) ; Check for pseudo commands
|
||
bne.s @OkExit ; On Pseudo Packets check the command
|
||
|
||
cmp.b #MaxPseudoCmd,pbCmd(a0) ; Validate the Pseudo command number <bg>
|
||
bls.s @OkExit
|
||
|
||
@BadPseudo move.w #InvPseudo,pbParam(a0) ; report a pseudo command error
|
||
move.w pbCmdType(a0),pbParam+2(a0) ; we are faking an error packet
|
||
bra.s @ErrorExit
|
||
|
||
@BadPkt move.w #InvPkt,pbParam(a0) ; report invalid packet error
|
||
move.w pbCmdType(a0),pbParam+2(a0) ; we are faking an error packet
|
||
|
||
@ErrorExit move.w #paramErr,pbResult(a0) ; parameter error in result field
|
||
bra.s @Exit
|
||
|
||
@OkExit move.w #0,pbResult(a0) ; So far packet OK
|
||
@Exit rts
|
||
|
||
ENDWITH
|
||
ENDPROC
|
||
|
||
;------------------------------------------------------------------
|
||
|
||
;__________________________________________________________________________ <101> <BEGIN>
|
||
; PACK 4 overpatch code for MC68020 software SANE to correct binary-to
|
||
; decimal conversion bug which may cause an extra byte to be written to
|
||
; the destination decimal record.
|
||
;
|
||
; Copyright © 1990 Apple Computer, Inc. All rights reserved.
|
||
; Written by: Jon Okada.
|
||
;
|
||
; The overpatch code intercepts every PACK 4 call and determines if the SANE
|
||
; operation requested is a binary-to-decimal conversion. If it is not,
|
||
; control is passed to the original, underlying SANE engine. If it is,
|
||
; the SANE engine is called with output directed to a local decimal record,
|
||
; which is copied to the user's destination decimal record, taking care not
|
||
; to exceed the desired precision.
|
||
;
|
||
; Entry point is FP020PATCH. Upon entry, the stack is as follows:
|
||
;
|
||
; &return < SANE opword (2 bytes) < &dst < &src < &src2,
|
||
;
|
||
; where &src and &src2 may not be present, depending on the SANE operation
|
||
; requested by the caller.
|
||
|
||
PACK4inROM equ $73940 ;Offset from ROMBase to non-fpu PACK4.
|
||
|
||
FP020Patch PROC
|
||
|
||
MOVE.L D0,-(SP) ; STACK: D0sv < &ret < opcode < etc.
|
||
MOVEQ #$1F,D0 ; D0 <- opcode mask
|
||
AND.W 8(SP),D0 ; isolate opcode
|
||
CMPI.B #$0B,D0 ; binary-to-decimal conversion?
|
||
MOVEM.L (SP)+,D0 ; (restore register)
|
||
BEQ.S @DOBINDEC ; yes
|
||
|
||
jmpROM PACK4inROM ; Let PACK4 handle call.
|
||
|
||
;
|
||
; Binary-to-decimal conversion is accomplished via the underlying PACK 4
|
||
; implementation, but the result is directed to an intermediate buffer
|
||
;
|
||
@DOBINDEC:
|
||
LINK A6,#-28 ; reserve space for decimal record
|
||
MOVEM.L D0/A0-A1,-(SP) ; save registers
|
||
|
||
LEA -28(A6),A0 ; A0 <- addr of local decimal record
|
||
|
||
MOVE.L 18(A6),-(SP) ; push &src2
|
||
MOVE.L 14(A6),-(SP) ; push &src
|
||
MOVE.L A0,-(SP) ; push local decimal record addr
|
||
MOVE.W 8(A6),-(SP) ; push opword
|
||
|
||
jsrROM PACK4inROM ; call pack4.
|
||
|
||
MOVEA.L 10(A6),A1 ; A1 <- &dst
|
||
MOVE.L (A0)+,(A1)+ ; copy sign/exp to dst record
|
||
CLR.W D0 ; clear counter
|
||
MOVE.B (A0)+,D0 ; read decimal string length
|
||
MOVE.B D0,(A1)+ ; write it to dst record
|
||
SUBQ #1,D0 ; initialize loop counter
|
||
|
||
@1:
|
||
MOVE.B (A0)+,(A1)+ ; copy string to dst record
|
||
DBRA D0,@1
|
||
|
||
MOVEM.L (SP)+,D0/A0-A1 ; restore registers
|
||
UNLK A6 ; unlink
|
||
MOVE.L (SP),14(SP) ; move return addr up
|
||
ADDA.W #14,SP ; kill arguments on stack
|
||
|
||
RTS ; return to caller
|
||
|
||
ENDP
|
||
;__________________________________________________________________________ <101> <END>
|
||
|
||
|
||
;__________________________________________________________________________ <xyz> <cch 8/6/91>
|
||
; Routine: GetPageDescPatch
|
||
;
|
||
; Function: This routine is a patch to the GetPageDescPatch, which is
|
||
; an internal routine called by LockMemory and WriteProtectMemory.
|
||
; The bug it fixes is that the page descriptor pointer is
|
||
; converted from physical to logical twice in GetPageDesc.
|
||
; This patch is only needed on 68030 machines with ROM version $67C,
|
||
; sub-version 1.5 without VM.
|
||
;
|
||
; How: This is a come-from patch to the _Gestalt trap, which is
|
||
; called by the GetMMUInfo routine in GetReal.a. If the
|
||
; come-from patch is triggered, and the GetPageProc flag on
|
||
; the stack is set, the return address from GetPageDescProc is
|
||
; replaced with the address of a routine which fixes the
|
||
; result and returns to the original caller.
|
||
;
|
||
; Note: This patch is NOT reentrant. This is OK, however, since
|
||
; _LockMemory may not be called at interrupt level, which is
|
||
; the only way reentrancy could occur with this routine.
|
||
;
|
||
; Inputs: A0/D0 - parameters to gestalt
|
||
; (sp).L - address routine was called from plus 2
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Destroys: a1
|
||
;__________________________________________________________________________
|
||
GetMMUInfoPatchAddr EQU $40886d1e ; return address when Gestalt is called
|
||
SetCacheInhibitAddr EQU $408873a2 ; return address when correct swapMMUMode is called
|
||
getPageDesc EQU 7 ; getPageDesc selector
|
||
|
||
GetPageDescPatch PROC
|
||
EXPORT MemDispPatch
|
||
|
||
cmp.l #GetMMUInfoPatchAddr,$18(sp) ; check addr _Gestalt was called from
|
||
bne.s @skipPatch ; IF we had a match THEN
|
||
cmp.w #getPageDesc,$4e(sp) ; check if user wants the page descriptor
|
||
bne.s @skipPatch ; IF user wants a page descriptor THEN
|
||
lea GetPageDescRetAddr,a1 ; where to save getPageDesc return addr
|
||
move.l $50(sp),(a1) ; save return address to getMMUInfo
|
||
lea fixResult,a1 ; get address of routine to fix result
|
||
move.l a1,$50(sp) ; stuff it in the stack frame
|
||
; ENDIF
|
||
; ENDIF
|
||
@skipPatch BackToTrap origGestalt ; jump to original Gestalt trap
|
||
|
||
;-----------------
|
||
; getPageDesc fix up routine
|
||
;-----------------
|
||
fixResult
|
||
sub.l Phys2Log,a0 ; fix up result
|
||
jmp ([GetPageDescRetAddr]) ; jump back into normal code stream
|
||
|
||
GetPageDescRetAddr ; return address for getMMUInfo
|
||
dc.l $87654321
|
||
|
||
;__________________________________________________________________________ <10> <cch 8/6/91>
|
||
; Routine: MemDispPatch
|
||
;
|
||
; Function: This routine is a patch to the _VM trap. It fixes a bug
|
||
; in the Terror ROM which occurs when the page the stack is
|
||
; is is marked uncacheable in the MMU tables, then a subsequent
|
||
; PFLUSH'd is executed with data still in the cache.
|
||
;
|
||
; How: This is a simple patch which is installed only on 68030's when
|
||
; VM is not installed on Terror ROMs, version $67C, sub-version 1.5.
|
||
; It disables the data cache during all _VM calls with the exception
|
||
; of _GetPhysical.
|
||
;
|
||
; Inputs: A0-A1/D0 - parameters to _VM call
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Destroys: d1
|
||
;__________________________________________________________________________
|
||
GetPhysSel EQU 5
|
||
|
||
MemDispPatch
|
||
cmp.b #GetPhysSel,d0 ; check for get physical selector
|
||
beq.s @skipPatch ; IF this is anything but getPhysical THEN
|
||
movec cacr,d1 ; get cache value
|
||
move.w d1,-(sp) ; save cache state on stack
|
||
andi.w #$001f,d1 ; we want to save current instruction cache bits
|
||
addi.w #$0800,d1 ; value to flush data cache
|
||
movec d1,cacr ; flush and disable data cache
|
||
jsrTrap origMemDisp ; do original call
|
||
move.w (sp)+,d1 ; get original cache state
|
||
movec d1,cacr ; reenable caches
|
||
rts ; return to caller
|
||
@skipPatch ; ELSE
|
||
BackToTrap origMemDisp1 ; do original call
|
||
; ENDIF
|
||
|
||
ENDP
|
||
;__________________________________________________________________________ <10> <end>
|
||
|
||
;__________________________________________________________________________ <13><cch 8/28/91>
|
||
; Routine: FP68k patch for Terror-based 030 machines
|
||
;
|
||
; Inputs: stack has: <RET> <OPWORD> <ADRS1> <ADRS2> <ADRS3>
|
||
;
|
||
; Destroys: d1
|
||
;__________________________________________________________________________
|
||
QADDX EQU $408EC1E4
|
||
FP881CASE EQU $408EB50C
|
||
OMEGA881BASE EQU $408EB1FC
|
||
OPERRHANDLER EQU $408EDCE6
|
||
|
||
FP68kPatch PROC EXPORT
|
||
|
||
tst.b MMU32bit ; Are we in 24 bit mode?
|
||
beq.s @inMode24 ; -> Yes
|
||
|
||
@inMode32 cmp.l #$40800000,(SP) ; check address we're patching
|
||
bhs.s @dontBackpatch ; IF we're being called from ROM THEN
|
||
@CallOld BackToTrap origFP68k ; do original call
|
||
|
||
@inMode24 move.l D0,-(SP) ; save D0
|
||
move.l 4(SP),D0 ; get Return address in D0
|
||
|
||
and.l MaskBC,D0 ; poor man's strip address
|
||
cmp.l #$00800000,D0 ; Is the PC less than ROM?
|
||
movem.l (SP)+,D0 ; Restore D0
|
||
blo.s @CallOld ; -> Yes, Call the old Backpatch routine
|
||
; No. Fall into DontBackPatch
|
||
|
||
@dontBackpatch ; ELSE
|
||
SUBQ #2,SP ; MAKE A HOLE
|
||
MOVEM.L D0/A0,-(SP) ; SAVE 2 REGISTERS
|
||
|
||
LEA QADDX,A0 ; ALWAYS STORE &QADDX INTO ITS JUMP ISLAND
|
||
MOVE.L A0,$0B6E ; HOME SO TRAPS HAVE A POINT OF REFERENCE
|
||
|
||
MOVE.W 14(SP),D0 ; GET OPWORD INTO D0
|
||
ROL.W #8,D0 ; XXXX383F --> XXXX3F38 ... SWAP BYTES
|
||
LSL.B #2,D0 ; XXXX3F38 --> XXXX3FE0 ... SCRUNCH TOGETHER
|
||
BFEXTS D0{18:9},D0 ; D0 ::= INDEX := 8 * OPCODE + FORMAT
|
||
MOVE (FP881CASE,D0*2),D0 ; DO := OFFSET AT INDEX IN TABLE
|
||
LEA OMEGA881BASE,A0 ; GET OMEGABASE
|
||
ADD.L D0,A0 ; GO DO IT
|
||
MOVE.L 10(SP),12(SP) ; SLIDE RETURN ADDRESS ON TOP OF OPWORD
|
||
MOVE.L A0,8(SP) ; FILL RTS HOLE PROVIDED ABOVE
|
||
|
||
LEA OPERRHANDLER,A0 ; INSTALL OPERR TRAP HANDLER INTO
|
||
MOVE.L A0,$0D0 ; LOW-MEM VECTOR (SEE TABLE 7-6 882 MAN)
|
||
|
||
FMOVE.L FPCR,D0 ; ENABLE OPERAND ERROR TRAPPING
|
||
BSET #13,D0
|
||
FMOVE.L D0,FPCR
|
||
|
||
MOVEM.L (SP)+,D0/A0 ; RESTORE 2 REGISTERS
|
||
RTS ; DISPATCH
|
||
|
||
; ENDIF
|
||
|
||
ENDP
|
||
;__________________________________________________________________________ <13>
|
||
|
||
|
||
;----------------------------------------------------------------------------------------------------
|
||
|
||
|
||
|
||
|
||
;=========================================================================================
|
||
;=========================================================================================
|
||
;= =
|
||
;= END OF RESIDENT PATCH CODE SECTION =
|
||
;= =
|
||
;=========================================================================================
|
||
;=========================================================================================
|
||
|
||
EndOfPatch PROC EXPORT
|
||
|
||
;=========================================================================================
|
||
;=========================================================================================
|
||
;= =
|
||
;= PATCH INSTALL CODE IS BELOW THIS POINT =
|
||
;= =
|
||
;= Patches may fall into two different categories: =
|
||
;= 1. Required for both the Mac OS and A/UX =
|
||
;= 2. Required only for the Mac OS =
|
||
;= =
|
||
;= Macintosh OS-only patches are usually characterized by code which touches hardware =
|
||
;= directly, or patches for traps not supported by A/UX. The safest thing to do when =
|
||
;= in doubt is to check with your friendly A/UX representative (only a phone call =
|
||
;= away!). A/UX loads all patches, but conditionalizes the installation code. The =
|
||
;= first section of installation code which follows, is for patches required on both =
|
||
;= Mac OS and A/UX. The second section (further down), is for Mac OS-only patch =
|
||
;= installation code. =
|
||
;= =
|
||
;= To find a place to add your Mac OS and A/UX patch, search for 'EndBothSection' =
|
||
;= =
|
||
;= To find a place to add your Mac OS only patch, search for 'EndMacSection' =
|
||
;= =
|
||
;=========================================================================================
|
||
;=========================================================================================
|
||
|
||
PatchInit MAIN Export
|
||
Import EndOfPatch
|
||
Import StartPatch
|
||
Import Cutback
|
||
Import FixupTbl ; added FixupTbl <24July89smb>
|
||
|
||
MOVE.L D1,-(SP) ; Save our handle <1.1-4april89-CEL>
|
||
|
||
;____________________________________________________________________________
|
||
; Fixup patch addresses
|
||
;
|
||
; The Fixing up of addresses generated by the CMPRA, JSRROM & JMPROM
|
||
; Breaks down as follows:
|
||
;
|
||
; Addressing High Byte in Action
|
||
; mode: instruction:
|
||
; ---------- ------------ ------
|
||
; 24 bit NZ Do not alter the address in the instruction.
|
||
; Used with CMPRA to a ROM Resource.
|
||
; 32 bit NZ Mask out 12 high bits from the address
|
||
; in the instruction, leaving a ROM offset
|
||
; Then add in ROMBase.
|
||
; either Zero Normal Case. Add ROMBase to the address
|
||
; in the instruction.
|
||
;
|
||
; Registers:
|
||
; D0: Address Size Flag. Pos: 24 bit mode; Neg: 32 bit Mode
|
||
; D1: Entry from table of offsets of locations to be fixed up
|
||
; D2: (RomBase)
|
||
; A0: Pointer into table of offsets of locations to be fixed up.
|
||
; A1: Base of fixup table; also location from which offsets are computed.
|
||
|
||
move.l RomBase, D2
|
||
moveq #-1, D0
|
||
_StripAddress
|
||
lea FixupTbl, A0
|
||
move.l A0, A1
|
||
FixUpLooP move.l (A0)+, D1
|
||
beq.s @1
|
||
tst.b 0(A1, D1.L)
|
||
beq.s @AddIt
|
||
tst.l D0 ; If Address has any high bits set
|
||
bpl.s FixUpLoop ; 24 Bit mode; Dont alter this one.
|
||
and.w #$f, 0(A1, D1.L); 32 Bit Mode; Clear High 12 bits.
|
||
|
||
@AddIt add.l D2, 0(A1, D1.L) ; Normal Case: Add in ROMBase
|
||
bra.s FixUpLoop
|
||
@1
|
||
move.l jCacheFlush, a0 ; flush caches (make sure tables are consistent)
|
||
jsr (a0)
|
||
|
||
|
||
|
||
;=========================================================================================
|
||
;=========================================================================================
|
||
;= =
|
||
;= PATCH INSTALLATION CODE FOR BOTH MAC OS AND A/UX STARTS HERE =
|
||
;= =
|
||
;= Please be neat and follow the format =
|
||
;= =
|
||
;=========================================================================================
|
||
;=========================================================================================
|
||
|
||
|
||
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ GGD <8.4>
|
||
; Fix _StripAddress to not check the MMStartMode bit of MMFlags at runtime,
|
||
; because the memory manager changes that bit when accessing ROM resources,
|
||
; and if an interrupt occurs while the bit is changed, calling _StripAddress
|
||
; from an interrupt routine (eg VBL task) might not work correctly. To correct
|
||
; this, we will install either a 24 or 32 bit version of _StripAddress once
|
||
; and eliminate the runtime check, making the code both faster and correct.
|
||
; NOTE: This is installed early in the patch file to reduce the chances of
|
||
; encountering this bug while installing the remaining patches.
|
||
|
||
StripAddressOld equ $0000D764 ; ROM offset of old StripAddress
|
||
StripAddress24 equ $0000D76C ; ROM offset of new 24 bit mode version
|
||
StripAddress32 equ $0000D770 ; ROM offset of new 32 bit mode version
|
||
|
||
FixStripAddress
|
||
lea OsTable+($55*4),a0 ; point to dispatch table entry (trap A055)
|
||
CmpRA StripAddressOld,(a0) ; see if it already patched (by A/UX maybe?)
|
||
bne.s @Done ; if already patched, don't patch again
|
||
moveq.l #StripAddress24-StripAddressOld,d0 ; get adjustment for 24 bit mode
|
||
btst.b #Systemis24bit,SystemInfo ; what kind of OS are we running
|
||
bne.s @patchIt ; if 24 bit OS, change it to 24 bit StripAddress
|
||
addq.l #StripAddress32-StripAddress24,d0 ; if 32 bit, adjust offset to 32 bit entry
|
||
@patchIt add.l d0,(a0) ; update the dispatch table entry
|
||
@done ; all done <8.4>
|
||
|
||
|
||
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ <8>
|
||
; The TERROR ROM does not distinguish between a Tim and a Tim LC. We have to.
|
||
; We need to fix boxFlag if we're running on a Tim LC (a Tim w/o an FPU)
|
||
;
|
||
MOVE.L ROMBase,A0 ; Get Bas o ROM
|
||
CMPI.B #TERRORMinorVers,18(A0) ; Is this a TERROR 67C ROM?
|
||
BNE.S @DoneTimLC ; -> Nope, don't futz with anything
|
||
|
||
CMPI.B #boxPowerBook170,boxFlag ; Does the ROM think this is a Tim? <146>
|
||
BNE.S @DoneTimLC ; -> No, don't assume anything. Bail out.
|
||
|
||
MOVE.W HwCfgFlags,D0 ; Get them Hardware Config Flags
|
||
BTST.L #hwCbFPU,D0 ; Does we gots an FPU?
|
||
BNE.S @DoneTimLC ; -> Yes, we're not on a Tim LC. Exit.
|
||
BTST.L #hwCbPwrMgr,D0 ; Do we have a PowerMgr?
|
||
BEQ.S @DoneTimLC ; -> No. This is not a Portable of any kind
|
||
; We're on a TERROR $67C ROM with a PwrMgr and no FPU.
|
||
MOVE.B #boxPowerBook140,boxFlag ; We're on a Tim LC. Stuff the right boxFlag <146>
|
||
@DoneTimLC
|
||
|
||
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ <130><131><8><9>
|
||
; The GestaltFuction.a file is used to build a ptch for machines without
|
||
; Gestalt in ROM, but it also contains fixes and improvements that are not
|
||
; in the ci ROMs OR in the GestaltPatches.a file... The changes are not
|
||
; trivial, so weÕre punting and loading the Gestalt ptch on ci ROMs, too...
|
||
;
|
||
; Before we do, though, we throw away any storage that Gestalt has allocated.
|
||
;
|
||
|
||
|
||
move.l ExpandMem,A1
|
||
move.l ExpandMemRec.emGestalt(A1),A0 ; Get the ROM GestaltÕs Storage pointer
|
||
move.l A0,-(SP) ; Save the Ptr on the Stack
|
||
move.l (A0),-(SP) ; Save Gestalt's Selector table handle
|
||
|
||
PtchInst 5 ; Reinstall all of Gestalt ptch
|
||
|
||
move.l (SP)+,A0 ; Get the old Selector Table Handle
|
||
_DisposHandle ; Throw the storage away!
|
||
move.l (SP)+,A0 ; Get the storage Ptr
|
||
_DisposPtr ; Make it go away too!
|
||
|
||
|
||
;____________________________________________________________________________ NJC <1.6>
|
||
; ci Quickdraw ptch added 1/16/90 KON
|
||
;
|
||
|
||
PtchInst 26 ; ci Quickdraw patches
|
||
|
||
;____________________________________________________________________________ DAF <1.9>
|
||
; Install window manager fixes
|
||
;
|
||
|
||
InstToolTp newSetWinColor,$241
|
||
InstToolTp NewSetCtlColor,$243
|
||
|
||
;____________________________________________________________________________ dvb <3.5>
|
||
; Palette Mgr Patches
|
||
;
|
||
|
||
InstToolTp ptchInitPalettes,$290
|
||
InstToolTp ptchGetNewCWindow,$246 ;<10Nov89 KON>
|
||
InstToolTp ptchPMgrDispatch,$2A2 ; Changed a couple of dispatches dvb <8.3>
|
||
; Next, fix up the dispatch table
|
||
LEA pMgrProcs,A0
|
||
MOVE.L A0,D1 ; D1-> base of table
|
||
SUBQ.L #1,D1 ; Less 1, 'coz lobit = patched flag
|
||
MOVE #((pMgrProcsSize)/4)-1,D0 ; we'll loop for this many fields <107> (pMgrProcsSize)
|
||
@FixPMLoop MOVE.L (A0),D2 ; pull entry from table
|
||
BTST #0,D2
|
||
BEQ.S @FixPMLoopEnd
|
||
ADD.L D1,D2
|
||
@FixPMLoopEnd MOVE.L D2,(A0)+ ; stash correct address, bump A0
|
||
DBRA D0,@FixPMLoop ; and count down, including zero. dvb <8.3> end
|
||
|
||
;__________________________________________________________________________
|
||
;__________________________________________________________________________
|
||
|
||
FixBackSANE MOVE.L #'fpu ',D0 ; Gestalt FPU selector
|
||
_Gestalt ; Do it
|
||
MOVE.L A0,D0 ; Do we have an FPU?
|
||
BEQ @ReallyDone ; -> No, do nothing
|
||
|
||
MOVE.L ROMBase,A0 ; Get ROM base
|
||
CMPI.B #TERRORminorVers,18(A0) ; Is this TERROR 067C ROM?
|
||
BEQ @ReallyDone ; -> Yes, leave the ROM SANE enabled!
|
||
CMPI.B #ZYDECOminorVers,18(A0) ; Is this Zydeco 067C ROM?
|
||
BEQ @ReallyDone ; -> Yes, leave the ROM SANE enabled!
|
||
|
||
@DisableSANEinROM
|
||
MOVE.B ResLoad,-(SP) ; Save current resLoad state
|
||
MOVE.W CurMap,-(SP) ; Save Current Rsrc Map refNum
|
||
CLR.W CurMap ; Make the System the current Map (CurMap = 0)
|
||
|
||
SF ResLoad ; Don't actually read the rsrc
|
||
CLR.L -(SP) ; Result
|
||
MOVE.L #'PACK',-(SP) ; Type
|
||
MOVE.W #4,-(SP) ; Id 4
|
||
_Get1Resource
|
||
MOVE.L (SP)+,D0 ; Did we get it?
|
||
BEQ @Done ; -> No, PACK 4 is not on the disk. Exit Now! (Use the ROM SANE)
|
||
MOVE.L D0,-(SP)
|
||
_ReleaseResource ; Make the System SANE handle go away. (or we'll get it at the _RmveRsrc)
|
||
|
||
SF ResLoad ; Don't actually read the rsrc
|
||
CLR.L -(SP) ; Result
|
||
MOVE.L #'PACK',-(SP) ; Type
|
||
MOVE.W #5,-(SP) ; Id 5
|
||
_Get1Resource
|
||
MOVE.L (SP)+,D0 ; Did we get it?
|
||
BEQ @Done ; -> No, PACK 5 is not on the disk. Exit Now! (Use the ROM SANE)
|
||
MOVE.L D0,-(SP)
|
||
_ReleaseResource ; Make the System SANE handle go away. (or we'll get it at the _RmveRsrc)
|
||
|
||
ST RomMapInsert ; Put the ROM map in first
|
||
MOVE.W #1,CurMap ; Make the ROM map current
|
||
|
||
CLR.L -(SP) ; Result
|
||
MOVE.L #'PACK',-(SP) ; Type
|
||
MOVE.W #4,-(SP) ; Id 4
|
||
_Get1Resource
|
||
MOVE.L (SP)+,D0 ; Did we get it?
|
||
BEQ.S @Try45 ; -> No, try 4 five.
|
||
|
||
MOVE.L D0,-(SP) ; The Handle (save a copy of it)
|
||
MOVE.L ROMMapHndl,-(SP) ; Save this
|
||
MOVE.L #-1,ROMMapHndl ; To fool SetResAttr into letting use change ROM rsrc attrs
|
||
|
||
MOVE.L D0,-(SP) ; The Handle (push it. Push it good)
|
||
MOVE.W #$50,-(SP) ; A good value (Unprotected)
|
||
_SetResAttrs
|
||
MOVE.L (SP)+,ROMMapHndl
|
||
|
||
MOVE.W #1,CurMap ; Set CurMap to the ROM rsrc map
|
||
ST RomMapInsert ; Dont load the rsrc into memory
|
||
_RmveResource
|
||
|
||
@Try45 ST RomMapInsert ; Put the ROM map in first
|
||
|
||
CLR.L -(SP) ; Result
|
||
MOVE.L #'PACK',-(SP) ; Type
|
||
MOVE.W #5,-(SP) ; Id 5
|
||
_Get1Resource
|
||
MOVE.L (SP)+,D0 ; Did we get it?
|
||
BEQ.S @Done ; -> No, exit
|
||
|
||
MOVE.L D0,-(SP) ; The Handle (save a copy of it)
|
||
MOVE.L ROMMapHndl,-(SP) ; Save this
|
||
MOVE.L #-1,ROMMapHndl ; To fool SetResAttr into letting use change ROM rsrc attrs
|
||
|
||
MOVE.L D0,-(SP) ; The Handle (push it. Push it good)
|
||
MOVE.W #$50,-(SP) ; A good value (Unprotected)
|
||
_SetResAttrs
|
||
MOVE.L (SP)+,ROMMapHndl
|
||
|
||
MOVE.W #1,CurMap ; Set CurMap to the ROM rsrc map
|
||
ST RomMapInsert ; Dont load the rsrc into memory
|
||
_RmveResource
|
||
|
||
@Done MOVE.W (SP)+,CurMap ; Restore the current res map
|
||
MOVE.B (SP)+,resLoad ; Restore ResLoad
|
||
@ReallyDone
|
||
;__________________________________________________________________________
|
||
;__________________________________________________________________________
|
||
|
||
|
||
|
||
;____________________________________________________________________________ <2> RMP
|
||
; This patch is used to fix a problem in the MPW Shell on Eclipse. See above.
|
||
|
||
ROMVIA2DT equ $00009D70 ; ROM offset of old IOP interrupt handler
|
||
|
||
bra.s EclipseMPWPatchEnd ; skip over patch body into install code
|
||
|
||
EclipseMPWPatchStart
|
||
|
||
move.b #1<<ifCA2,VIFR(A1) ; reset the VIA2 interrupt flag
|
||
move.l #(%00001000<<24)+\ ; allow xmt msg 3 (ADB)
|
||
(%00001000<<16)+\ ; allow rcv msg 3 (ADB)
|
||
(0<<8)+\ ; this byte must be zero
|
||
1,d0 ; ADB is on SWIM IOP (IOP 1)
|
||
jmpROM IOPInterrupt ; handle the interrupt and return
|
||
|
||
EclipseMPWPatchEnd
|
||
@EclipseMPWPatchSize equ EclipseMPWPatchEnd-EclipseMPWPatchStart
|
||
|
||
|
||
cmpRA ROMVIA2DT,(VIA2DT+4*ifCA2) ; see if we have an IOP interrupt handler
|
||
bne.s @done ; if not, don't need to install it
|
||
|
||
moveq.l #@EclipseMPWPatchSize,d0; space needed
|
||
_NewPtr ,Sys,Clear ; allocate it
|
||
bne.s @done ; if can't allocate, don't install
|
||
movea.l a0,a1 ; dest address
|
||
lea EclipseMPWPatchStart,a0 ; source address
|
||
moveq.l #@EclipseMPWPatchSize,d0 ; byte count
|
||
_BlockMove ; copy the code
|
||
|
||
move.w sr,-(sp) ; save old int level
|
||
ori.w #HiIntMask,sr ; disable all ints
|
||
|
||
move.l a1,(Via2DT+4*ifCA2) ; install the new VIA2 interrupt handler
|
||
|
||
move.w (sp)+,sr ; restore the interrupt level
|
||
|
||
@done
|
||
|
||
; End of Eclipse Cmd-Shift-Esc patch
|
||
;____________________________________________________________________________ <2> RMP
|
||
|
||
|
||
;____________________________________________________________________________ GGD <2.0>
|
||
; SANE Package Optimization
|
||
;
|
||
; Optimize the SANE packages which are ROM Resources, by having the dispatch
|
||
; table entry point right to the first instruction of the package, instead
|
||
; of going through the Package Manager which finds the package by de-referencing
|
||
; a handle.
|
||
;
|
||
|
||
IF 1 THEN ; removed <4.6> <08/21/89 pke> re-enabled 11/29/89 <8.4>
|
||
OptimizePACKs
|
||
lea @PackOptTable,a3; point to the optimization table
|
||
@optLoop move.w (a3)+,d0 ; get the package number
|
||
bmi.s @done ; exit at end of list
|
||
move.w d0,-(sp) ; push the package number
|
||
_InitPack ; get the ROM resource, update AppPacks table
|
||
move.w (a3)+,d1 ; get the trap word
|
||
move.w (a3)+,a0 ; get the low mem address
|
||
move.l (a0),d0 ; get the handle
|
||
beq.s @optLoop ; if null, skip it
|
||
movea.l d0,a0 ; setup to de-reference it
|
||
move.l (a0),d0 ; get a pointer to the routine
|
||
beq.s @optLoop ; if null, skip it
|
||
movea.l d0,a0 ; setup pointer to code
|
||
cmpi.b #$60,(a0) ; see if first instruction is a BRA.S
|
||
bne.s @branchOptDone ; if not, don't optimize it
|
||
move.w (a0)+,d0 ; get the BRA.S instruction
|
||
ext.w d0 ; extend the branch displacement
|
||
adda.w d0,a0 ; update the entry point address
|
||
@branchOptDone
|
||
move.w d1,d0 ; setup the trap word
|
||
_SetTrapAddress ; go directly to the first instr of the package
|
||
bra.s @optLoop ; optimize the next package
|
||
|
||
@PackOptTable
|
||
dc.w 4 ; package number 4
|
||
_FP68K ; trap name for PACK 4
|
||
dc.w AppPacks+4*4 ; low mem address of handle to PACK 4
|
||
|
||
dc.w 5 ; package number 5
|
||
_Elems68K ; trap name for PACK 5
|
||
dc.w AppPacks+5*4 ; low mem address of handle to PACK 5
|
||
|
||
dc.w -1 ; package number -1, end of list
|
||
@done
|
||
ENDIF
|
||
|
||
;__________________________________________________________________________ <101> <BEGIN>
|
||
;
|
||
; Install PACK 4 patch if:
|
||
;
|
||
; - BoxFlag = 13 (//si - Erickson), or 14 (Mac LC - Elsie)
|
||
; and - No FPU present
|
||
; and - Current non-fpu PACK 4 lives at ROMBase + $73940
|
||
;
|
||
; NOTE: This code MUST execute after OptimizePACKs!
|
||
;
|
||
|
||
FP68KTrap equ $A9EB ;Trap number.
|
||
PACK4Handle equ AppPacks+16 ;Lomem contains PACK4 handle.
|
||
PACKID equ 4 ;Resource ID.
|
||
|
||
PACK4Patch
|
||
;
|
||
; Are we running on IIsi or LC?
|
||
;
|
||
|
||
; Commented out boxFlag check. Its not really needed. <107> SAM
|
||
; cmpi.b #boxMacLC,BoxFlag ;Is this an LC?
|
||
; beq.s @doPatch ;Yep, so install patch.
|
||
; cmpi.b #boxErickson,BoxFlag ;No, is it a IIsi?
|
||
; bne @endPACK4Patch ;Nope, so skip install.
|
||
;
|
||
; Yes, is there an FPU?
|
||
;
|
||
@doPatch move.l #gestaltFPUType,d0 ;Do we have an FPU?
|
||
_Gestalt
|
||
cmp.w #gestaltNoFPU,a0
|
||
bne @endPACK4Patch ;Yes, so don't install.
|
||
;
|
||
; Nope, does the current PACK4 live at ROMBase + $73940?
|
||
;
|
||
move.w #FP68KTrap,d0 ;Get trap number.
|
||
_GetTrapAddress ;Get current vector in a0.
|
||
cmpra PACK4inROM,a0 ;Matching address?
|
||
bne.s @endPACK4Patch ;Nope, so don't install.
|
||
;
|
||
; Yes, so install the patch...
|
||
;
|
||
move.w #FP68KTrap,d0 ;Get trap number.
|
||
lea FP020Patch,a0 ;Get address of our patch code.
|
||
_SetTrapAddress ;Patch it.
|
||
|
||
@endPACK4Patch
|
||
|
||
;__________________________________________________________________________ <101> <END>
|
||
|
||
;____________________________________________________________________________
|
||
; Gestalt parity calculation
|
||
;
|
||
; This code figures out if the board has parity capability, and if so,
|
||
; if there are parity SIMMs installed. It stores the result in the
|
||
; gestalt parity function in the resident portion of the patch above.
|
||
;
|
||
IMPORT parityValue
|
||
WITH DecoderInfo,ExpandMemRec,GestaltGlobals,ProductInfo
|
||
MACHINE MC68030
|
||
|
||
movem.l a3/a4/d3/d4,-(sp) ; save registers! <102>
|
||
|
||
movea.l ExpandMem,a0 ; get ptr to expandmem rec
|
||
movea.l emGestalt(a0),a0 ; get gestalt global ptr
|
||
clr.l d0 ; assume no parity, clear result <59>
|
||
cmpi.w #gestaltMacIIci,machType(a0) ; Mac IIci is first parity machine
|
||
blt @parityExit ; if before ci, definitely no parity
|
||
move.l UnivROMFlags,d1 ; get external feature bits
|
||
btst #PGCInstalled,d1 ; check if a parity chip exists
|
||
bne.s @checkPGC ; yep, go see if parity is enabled
|
||
move.l AddrMapFlags,d1 ; get universal info attributes
|
||
btst #RPUExists,d1 ; do we have an RPU chip?
|
||
bne.s @checkRPU ; then go check RPU
|
||
bra @parityExit ; if not, return zero as result
|
||
|
||
; checkPGC - check the parity VIA bit to see if it is enabled.
|
||
|
||
@checkPGC move.l VIA,a0 ; load up Via base address
|
||
btst #6,VBufB(a0) ; check if parity enabled
|
||
beq @parityOn ; if clear, parity is enabled
|
||
bra @parityOff ; otherwise, it's off
|
||
|
||
; checkRPU - First set RPU to generate bad parity, then access all four SIMMs in
|
||
; both banks by accessing location 0 and the last longword in memory.
|
||
; Parity is only fully active if all four SIMMs generate a parity interrupt.
|
||
; trashes a0/a1/a3/a4/d1-d4
|
||
|
||
@checkRPU movec cacr,d3 ; get contents of cache
|
||
move.l d3,-(sp) ; save them
|
||
move.l #$1111,d3 ; enable caches with bursting <32>
|
||
movec d3,cacr ; write into cache register <32>
|
||
move.l RomBase,a0 ; point to base of rom <32>
|
||
move.l #$2000,d3 ; cache size/long = 32k/4 = 8k <32>
|
||
@fillLoop tst.l (a0)+ ; load a long <32>
|
||
dbra d3,@fillLoop ; keep doing it for 8k <32>
|
||
move.l #$0808,d3 ; disable and freeze caches (bursting off)
|
||
movec d3,cacr ; write into cache register
|
||
move.l UnivInfoPtr,a0 ; get pointer to universal information
|
||
add.l (a0),a0 ; point to decoderInfo record
|
||
move.l RPUAddr(a0),a1 ; get RPU base address
|
||
move.l sp,d3 ; save our stack pointer
|
||
move.l AutoInt7,d4 ; save NMI vector
|
||
lea @parityInt,a4 ; address to return to from parity intrpt
|
||
lea @nmiHandler,a0 ; get address of our NMI handler
|
||
move #$2700,sr ; turn all interrupts off
|
||
move.l a0,AutoInt7 ; point vector to our handler
|
||
moveq #0,a3 ; check first bank (0 is in first bank)
|
||
|
||
@checkBank moveq #4-1,d2 ; check all four SIMMs
|
||
move.l (a3),d1 ; get contents of longword
|
||
@nextByte clr.l (a3) ; write a long with correct parity <44>
|
||
st.b rpuReset(a1) ; reset serial ptr
|
||
st.b (a1) ; write wrong parity mode
|
||
clr.b (a3,d2.w) ; write one SIMM with bad parity
|
||
|
||
st.b rpuReset(a1) ; reset serial ptr <105>
|
||
clr.b (a1) ; write good parity mode <105>
|
||
|
||
tst.l (a3) ; parity error if it's a parity SIMM
|
||
nop ; wait for an interrupt
|
||
nop
|
||
|
||
move.l d1,(a3) ; restore contents of longword
|
||
move #$2000,sr ; turn interrupts back on
|
||
move.l d4,AutoInt7 ; restore NMI vector
|
||
move.l (sp)+,d3 ; get original state of cache <17>
|
||
movec d3,cacr ; restore original state of cache <17>
|
||
bra.s @parityOff ; if we get here, it's a non-parity SIMM
|
||
|
||
@parityInt st.b rpuReset(a1) ; sync up RPU serial line
|
||
clr.b (a1) ; write good parity mode
|
||
dbra d2,@nextByte ; go check next SIMM
|
||
|
||
@allParityBank move.l d1,(a3) ; restore contents of longword
|
||
move.l a3,d1 ; did we just check location 0?
|
||
bne.s @restoreNMI ; if not, we're done and parity is on
|
||
movea.l ExpandMem,a0 ; get ptr to expandmem rec
|
||
movea.l emGestalt(a0),a0 ; get gestalt global ptr
|
||
movea.l memSize(a0),a3 ; total amount of memory
|
||
subq #4,a3 ; point to last longword in memory
|
||
bra.s @checkBank ; go check bank B
|
||
|
||
@restoreNMI move #$2000,sr ; turn interrupts back on
|
||
move.l d4,AutoInt7 ; restore NMI vector
|
||
move.l (sp)+,d3 ; get original state of cache <17>
|
||
movec d3,cacr ; restore original state of cache <17>
|
||
bra.s @parityOn ; go return that parity is on
|
||
|
||
; Interrupt handler for checkRPU routine. It is assumed that the NMI button is
|
||
; not pressed during this routine.
|
||
; d3 = stack pointer of routine
|
||
; a1 = RPU base address
|
||
; a4 = return address
|
||
|
||
@nmiHandler st.b rpuReset(a1) ; reset serial ptr
|
||
clr.b (a1) ; write good parity mode
|
||
st.b (a1) ; clear the parity error
|
||
move.l d3,sp ; restore the stack pointer
|
||
jmp (a4) ; return to the checkRPU routine
|
||
|
||
@parityOn bset #gestaltParityEnabled,d0 ; by here it is
|
||
|
||
@parityOff bset #gestaltHasParityCapability,d0 ; set parity capability bit
|
||
|
||
@parityExit lea parityValue,a0 ; get address of variable in gestalt function
|
||
move.l d0,(a0) ; save response in gestalt function
|
||
movem.l (sp)+,a3/a4/d3/d4 ; restore registers! <102>
|
||
|
||
ENDWITH
|
||
|
||
|
||
;____________________________________________________________________________
|
||
; Gestalt function patch installation
|
||
;
|
||
; These functions either did not make it in the Portable ROM, or changed
|
||
; between ROM final and System Disk final.
|
||
;
|
||
gestaltRBVAddr EQU 'rbv '
|
||
gestaltSCCReadAddr EQU 'sccr'
|
||
gestaltSCCWriteAddr EQU 'sccw'
|
||
gestaltVIA1Addr EQU 'via1'
|
||
gestaltVIA2Addr EQU 'via2'
|
||
gestaltSlotAttr EQU 'slot' ; removed in favor of gestaltNuBusConnectors <95>
|
||
gestaltFirstSlot EQU 'slt1' ; removed in favor of gestaltNuBusConnectors <95>
|
||
gestaltSlotCount EQU 'nubs' ; removed in favor of gestaltNuBusConnectors <95>
|
||
|
||
lea gestaltQDVers,a0 ; address of gestaltQDVersion patch
|
||
move.l #gestaltQuickdrawVersion,d0 ; selector to REPLACE
|
||
_ReplaceGestalt
|
||
|
||
lea gestaltAddrMode,a0 ; addr of gestaltAddressingModeAttr patch
|
||
move.l #gestaltAddressingModeAttr,d0 ; selector to REPLACE
|
||
_ReplaceGestalt
|
||
|
||
lea gestaltParity,a0 ; addr of gestaltParityAttr patch
|
||
move.l #gestaltParityAttr,d0 ; selector to REPLACE
|
||
_ReplaceGestalt
|
||
|
||
lea getGestaltVers,a0 ; addr of getGestaltVersion patch
|
||
move.l #gestaltVersion,d0 ; selector to REPLACE
|
||
_ReplaceGestalt
|
||
|
||
lea gestaltMisc,a0 ; addr of gestaltMisc patch
|
||
move.l #gestaltMiscAttr,d0 ; selector to ADD
|
||
_NewGestalt
|
||
|
||
lea gestaltNBCon,a0 ; addr of gestaltNuBusConnectors patch <95>
|
||
move.l #gestaltNuBusConnectors,d0 ; selector to ADD
|
||
_NewGestalt
|
||
|
||
lea gestaltUndef,a0 ; addr of gestaltUndef patch <95>
|
||
move.l #gestaltSlotAttr,d0 ; selector to REPLACE
|
||
_ReplaceGestalt
|
||
|
||
lea gestaltUndef,a0 ; addr of gestaltUndef patch <95>
|
||
move.l #gestaltFirstSlot,d0 ; selector to REPLACE
|
||
_ReplaceGestalt
|
||
|
||
lea gestaltUndef,a0 ; addr of gestaltUndef patch <95>
|
||
move.l #gestaltSlotCount,d0 ; selector to REPLACE
|
||
_ReplaceGestalt
|
||
|
||
lea gestaltNMgr,a0 ; addr of gestaltNotificationMgrAttr patch
|
||
move.l #gestaltNotificationMgrAttr,d0 ; selector to ADD
|
||
_NewGestalt
|
||
|
||
lea gestaltSerial,a0 ; addr of gestaltSerialAttr patch <95>
|
||
move.l #gestaltSerialAttr,d0 ; selector to ADD
|
||
_NewGestalt
|
||
|
||
lea gestaltUndef,a0 ; addr of gestaltUndef patch
|
||
move.l #gestaltRBVAddr,d0 ; selector to REPLACE
|
||
_ReplaceGestalt
|
||
|
||
lea gestaltUndef,a0 ; addr of gestaltUndef patch
|
||
move.l #gestaltSCCReadAddr,d0 ; selector to REPLACE
|
||
_ReplaceGestalt
|
||
|
||
lea gestaltUndef,a0 ; addr of gestaltUndef patch
|
||
move.l #gestaltSCCWriteAddr,d0 ; selector to REPLACE
|
||
_ReplaceGestalt
|
||
|
||
lea gestaltUndef,a0 ; addr of gestaltUndef patch
|
||
move.l #gestaltVIA1Addr,d0 ; selector to REPLACE
|
||
_ReplaceGestalt
|
||
|
||
lea gestaltUndef,a0 ; addr of gestaltUndef patch
|
||
move.l #gestaltVIA2Addr,d0 ; selector to REPLACE
|
||
_ReplaceGestalt
|
||
|
||
|
||
IF doScriptMgrGestalt AND (NOT installScriptMgrPtch27) THEN ; <6.1><50>
|
||
;____________________________________________________________________________ pke <2.5>
|
||
; Gestalt install for Script Mgr <2.5> <08/05/89 pke>
|
||
;
|
||
|
||
import gestaltScriptMgr,gestaltSMgrTable
|
||
|
||
lea gestaltSMgrTable,a3 ; table of Gestalt selectors
|
||
; and GetEnvirons verbs
|
||
@loopInstallGestalt
|
||
move.l (a3)+,d0 ; get next Gestalt selector
|
||
beq.s @doneInstallGestalt ; 0 means we're done
|
||
addq.l #2,a3 ; skip GetEnvirons verb
|
||
lea gestaltScriptMgr,a0 ; push gestaltFunction ProcPtr
|
||
_NewGestalt
|
||
; ignore OSErr in d0 (what can
|
||
; we do if it is not noErr?)
|
||
bra.s @loopInstallGestalt
|
||
@doneInstallGestalt
|
||
|
||
ENDIF ; <6.1>
|
||
|
||
|
||
;____________________________________________________________________________ dba <3.7>
|
||
; Install default colors 'clut' from System file
|
||
; Since the first InitGraf was before the ROvr code, the ROM 'clut' is
|
||
; always used. We want to use a better 'clut' from the System file.
|
||
; NOTE: This code is straight out of GrafAsm.a.
|
||
|
||
FixQDColors ; <4.7>
|
||
cmp.l #-1,QDColors ; is QDColors initialized? <4.7>
|
||
beq.s @done ; no, no need to fix it up <4.7>
|
||
|
||
SUBQ #4,SP ; make room for function result
|
||
MOVE #DefQDColors,-(SP) ; push resource ID
|
||
_GetCTable ; get default colors
|
||
|
||
MOVE.L QDColors,a0 ; get pointer to QDColors
|
||
|
||
MOVE.L (SP),A1 ; get handle to default colors
|
||
MOVE.L (A1),A1 ; point to default colors
|
||
ADD #CTTable,A1 ; skip over header
|
||
MOVEQ #15,D0 ; need to move 16 longs
|
||
@nextLong MOVE.L (A1)+,(A0)+ ; move a long
|
||
DBRA D0,@nextLong ; => repeat for all longs
|
||
|
||
_DisposCTable ; dispose of color table
|
||
@done ; <4.7>
|
||
|
||
|
||
;____________________________________________________________________________ dba <3.0>
|
||
; Install Menu Manager patches
|
||
;
|
||
|
||
InstToolTp NewInitProcMenu,$8
|
||
InstToolTp NewMenuSelect,$13D
|
||
|
||
|
||
IF NOT SPLINE_FONT THEN
|
||
;____________________________________________________________________________ cel <5>
|
||
; Install NewRSect Patch for DrawText zero width chars
|
||
;
|
||
setTrap NewRSect,$AB21
|
||
ENDIF
|
||
|
||
|
||
;____________________________________________________________________________ DAF <4.1>
|
||
; This really didn't get in until <5.1>
|
||
;
|
||
; Install SetEntries patch
|
||
|
||
|
||
InstToolTp mySaveEntries,$249
|
||
InstToolTp mySetEntries,$23F ; < 124 >
|
||
|
||
;____________________________________________________________________________ pke <4.6>
|
||
; Install patches to UprString,CmpString,RelString (OK for A/UX)
|
||
|
||
InstOSTp NewUprString,$54
|
||
InstOSTp NewCmpString,$3C
|
||
InstOSTp NewRelString,$50
|
||
|
||
;____________________________________________________________________________ DDG <58>
|
||
; Install vector for the ÒFPU not installedÓ dialog box if we donÕt have an
|
||
; FPU or an MMU
|
||
|
||
move.l #gestaltFPUType,d0 ;do we have an FPU ?
|
||
_Gestalt
|
||
cmp.w #gestaltNoFPU,a0 ;if this is NOT noFPU, then we skip
|
||
bne.s @skipInstall ;..the installation of this patch
|
||
|
||
lea NewFLineRoutine,a0 ;get the address of our F-Line routine into A0
|
||
lea OldFLineRoutine,a1 ;get the address of the JMP to the old F-Line routine
|
||
|
||
lea Line1111,A2
|
||
move.l (A2),2(A1) ; Save the old Vector <107> SAM
|
||
move.l A0,(A2) ; Make 1111 traps come to us first <107> SAM
|
||
|
||
@skipInstall
|
||
;----------------------------------------------------------------------------------------------------
|
||
|
||
|
||
;__________*** This set of routines gets run only if we have a REgret chip ***_________________
|
||
|
||
WITH ProductInfo
|
||
; <101> SAM
|
||
MOVE.L UnivROMFlags,D0 ; Do we have a REgret?
|
||
AND.B #ClockMask,D0 ; (bits 4-6) <107> SAM (Use ClockMask!)
|
||
CMP.B #ClockEgret,D0 ; Is bit 5 on?
|
||
BNE.S @EndOfEgretOnly ; -> Nope, skip this install code
|
||
|
||
;----------------------------------------------------------------------------------------------------
|
||
; This patch bypasses the physical read of egret when reading the time. The time is automatically
|
||
; updated in the background, therefore the low mem global always reflects the acurate time.
|
||
; (REgret only)
|
||
;----------------------------------------------------------------------------------------------------
|
||
|
||
InstOSTp RdDateTimePtch,$39
|
||
|
||
;----------------------------------------------------------------------------------------------------
|
||
; Install the TickHandler Patch into the TickComp vector kept in <89><101>
|
||
; the Egret Manager Global variables.
|
||
; (REgret only)
|
||
;----------------------------------------------------------------------------------------------------
|
||
|
||
WITH EgretGlobals
|
||
|
||
; Dont need to turn off IRQs here. <107> SAM
|
||
; move.w sr,-(sp) ; no interruptions
|
||
; ori.w #LVL7IRQ,sr
|
||
lea TickHandler,a0 ; get TickHandler address
|
||
move.l EgretBase,a1 ; point to EgretManager Globals
|
||
move.l a0,tickComp(a1) ; setup vector to new tick handler
|
||
; move.w (sp)+,sr ; restore interrupt state
|
||
|
||
ENDWITH
|
||
;----------------------------------------------------------------------------------------------------
|
||
; This patch will save the processor status register, call the <101> SAM
|
||
; ShiftRegIrq routine in Egret Manager and then restore the
|
||
; status register and exits.
|
||
; (REgret only)
|
||
;----------------------------------------------------------------------------------------------------
|
||
|
||
lea Vector_hold,a1 ; point to the interrupt vector placeholder
|
||
move.l LVL1DT+8,(a1) ; shift register interrupt handler
|
||
lea EgretIRQPtch,a1 ; Point to the patch
|
||
move.l a1,LVL1DT+8
|
||
|
||
|
||
;----------------------------------------------------------------------------------------------------
|
||
; This patch fixes possible loss of data to the SCC by calling <101> SAM
|
||
; the Poll Proc when SCC data is available.
|
||
; (REgret only)
|
||
;----------------------------------------------------------------------------------------------------
|
||
|
||
InstOSTp EgretDispatchPtch, $92
|
||
|
||
|
||
@EndOfEgretOnly
|
||
ENDWITH
|
||
;__________________________ End of REgret Only Section ______________________________________
|
||
|
||
|
||
|
||
;----------------------------------------------------------------------------------------------------
|
||
move.l MinusOne, $B50 ; clean up after netbooting socket listener.<78>
|
||
;----------------------------------------------------------------------------------------------------
|
||
|
||
|
||
;____________________________________________________________________________ pke <90>
|
||
; Move Script Mgr patches here so they are installed for A/UX. <90>
|
||
; Currently assumes that installScriptMgrPtch39 and installScriptMgrPtch27 are
|
||
; true, but this may be changed, so the inner conditionals are being left in.
|
||
|
||
IF doScriptMgrForAUX THEN ; <90>
|
||
|
||
IF installScriptMgrPtch39 THEN ; <50>
|
||
PtchInst 39 ; <42>
|
||
ENDIF
|
||
IF installScriptMgrPtch27 THEN ; <50>
|
||
PtchInst 27 ; <5.7>
|
||
ENDIF
|
||
|
||
ENDIF ; <90>
|
||
|
||
|
||
EndBothSection
|
||
;=========================================================================================
|
||
;=========================================================================================
|
||
;= =
|
||
;= ALL PATCHES BELOW THIS POINT ARE INSTALLED ON THE MACINTOSH OS ONLY. ALL PATCHES =
|
||
;= ABOVE THIS POINT ARE INSTALLED BOTH THE MAC OS AND A/UX. =
|
||
;= =
|
||
;=========================================================================================
|
||
;=========================================================================================
|
||
|
||
; Runtime check to determine whether we are running A/UX. If so, skip this section
|
||
; of patch install code.
|
||
|
||
move.w HwCfgFlags,d0 ; check Ôem the compulsive way
|
||
btst.l #hwCbAUX,d0 ; is it A/UX time?
|
||
bne skipMacOnlyPatches ; if so skip the mac-only patches
|
||
|
||
|
||
|
||
;=========================================================================================
|
||
;=========================================================================================
|
||
;= =
|
||
;= PATCH INSTALLATION CODE FOR THE MAC OS ONLY STARTS HERE =
|
||
;= =
|
||
;= Please be neat and follow the format =
|
||
;= =
|
||
;=========================================================================================
|
||
;=========================================================================================
|
||
|
||
|
||
|
||
;____________________________________________________________________________ ggd <2.2/2.7>
|
||
; Slot Interrupt patch
|
||
;
|
||
; Patches _SIntInstall, and reverses Slot interrupt queue order
|
||
;
|
||
|
||
PatchSIntInstall
|
||
Import SIntInstall
|
||
With SlotIntQElement,slotIntGlobals
|
||
|
||
; We reverse the order of equal priority elements in the queue for Aurora, such that
|
||
; they again blissfully agree with what the Mac II does for Equal Priorities
|
||
|
||
; turn off interrupts since we are mucking with a queue
|
||
move.w SR, -(sp)
|
||
ori.w #HiIntMask,SR ; disable all ints
|
||
InstOSTp SIntInstall,$A075 ; install the new trap
|
||
|
||
; cycle thru the slots for reversing queue order
|
||
moveq #TotalSlots-1,d1 ; set up for dbra
|
||
|
||
@nextQueue lea ([SlotQDT],d1.w*4,slotIntQHeads),a0 ; get address of queue header
|
||
movea.l (a0),a1 ; get ptr to first queue element
|
||
clr.l (a0) ; destroy old queue
|
||
bra.s @start ; re-install the elements
|
||
|
||
@loop movea.l a1,a0 ; set up for SIntinstall
|
||
movea.l SQLink(a1),a1 ; save out ptr to next queue element
|
||
move.l d1,d0 ; set up for call
|
||
_SIntInstall ; re-install the queue element
|
||
@start move.l a1,d0 ; test for end of queue
|
||
bne.s @loop ; loop until end of queue
|
||
|
||
@queueDone dbra d1,@nextQueue
|
||
|
||
; re-enable interrupts now that we are finished mucking
|
||
move.w (sp)+, SR
|
||
|
||
|
||
|
||
;____________________________________________________________________________ djw <2.4>
|
||
; Slot manager PRAM patch
|
||
;
|
||
; Fixes a problem in InitPRAMRecs where when initializing slot PRAM from a
|
||
; PRAM initialization record from the declaration ROM, the board id would
|
||
; not be set correctly. This code writes the correct board id to the slot
|
||
; PRAM for all good cards.
|
||
|
||
GetBoardROM Equ $0000636E ; addr of GetBoard routine in ROM <2.7>
|
||
|
||
With spBlock,sInfoRecord
|
||
FixSlotPRAM
|
||
suba.w #spBlockSize,sp ; alloc spBlock
|
||
movea.l sp,a0 ; a0 = ptr to spBlock
|
||
subq.l #8,sp ; alloc space for pram buffer
|
||
movea.l sp,a1 ; a1 = ptr to pram read/write buffer
|
||
clr.l (a1) ; clr pram buffer (8 bytes)
|
||
clr.l 4(a1)
|
||
clr.b spSlot(a0) ; start from slot zero
|
||
|
||
; Loop through the slots and check if the board id in PRAM matches the
|
||
; board id on the declaration ROM. If not, then write the correct one
|
||
; to PRAM.
|
||
|
||
move.w sr,-(sp) ; save status reg
|
||
ori.w #HiIntMask,sr ; disable interrupts
|
||
@Loop
|
||
jsrROM GetBoardROM ; jsr into ROM to GetBoard routine to get board sRsrc
|
||
bne.s @EndLoop ; no board sRsrc - skip this slot
|
||
movea.l spResult(a0),a2 ; a2 = ptr to sInfo record
|
||
tst.w siInitStatusA(a2) ; test card status
|
||
bmi.s @EndLoop ; bad slot - skip it
|
||
move.b #Boardid,spId(a0) ; read board id field from board sRsrc
|
||
_sReadWord
|
||
bne.s @EndLoop ; board id is gone - must be a bad slot
|
||
move.w spResult+2(a0),d1 ; reg d1 = board id from decl rom
|
||
|
||
move.l a1,spResult(a0) ; pass ptr to buffer
|
||
_sReadPRAMRec
|
||
bne.s @EndLoop ; cannot read PRAM - bad slot
|
||
|
||
; Compare PRAM board id with declaration ROM board id. If different, update
|
||
; the PRAM board id.
|
||
|
||
cmp.w (a1),d1 ; same board id's?
|
||
beq.s @EndLoop ; same - go to next slot
|
||
move.w d1,(a1) ; update board id in buffer
|
||
move.l a1,spsPointer(a0) ; set pointer to write buffer
|
||
_InitSlotPRAM
|
||
|
||
@EndLoop
|
||
addq.b #1,spSlot(a0) ; inc to next slot
|
||
cmp.b #sLastSlot,spSlot(a0)
|
||
ble.s @Loop ; continue till all slots are done
|
||
|
||
move.w (sp)+,sr ; restore interrupts
|
||
adda.w #spBlockSize+8,sp
|
||
|
||
Endwith
|
||
|
||
|
||
|
||
;____________________________________________________________________________ djw <3.6>
|
||
; Slot manager pInitEntry patch
|
||
;
|
||
; Install the pInitEntry patch which corrects the spId passed to _sFindDevBase
|
||
; from _InsertSRTRec.
|
||
;
|
||
Import pInitEntry
|
||
lea pInitEntry,a0 ; entry point for resident patch
|
||
move.l a0,([SDMJmpTblPtr],InitEntry*4) ; insert addr in slot mgr tbl
|
||
|
||
|
||
;____________________________________________________________________________ DAF <2.6>
|
||
; TFB Video Driver Override
|
||
;
|
||
INCLUDE 'VideoPatch.a'
|
||
|
||
;________________________________________________________________ <4.3><08/21/89 pke>
|
||
; Patch to Pack6 to fix Script Manager routines (which are not
|
||
; supported by A/UX).
|
||
;
|
||
IF doScriptMgrPack6Fix AND (NOT installScriptMgrPtch39) THEN ; <42><50>
|
||
InstToolTp ptchPack6,$1ED
|
||
ENDIF
|
||
|
||
;____________________________________________________________________________
|
||
; Bump Script Manager version number for IntlForce bug fix (SysVers < $700) pke <5.3>
|
||
; Set Script Manager version (SysVers >= $700) pke <5.7>
|
||
; redo using new symbol smgrVersPTCHRom pke <5.9>
|
||
|
||
IF doScriptMgrSetROMVers AND (NOT installScriptMgrPtch39) THEN ; <42><50>
|
||
With SMgrRecord
|
||
GetSMgrCore a0
|
||
move.w #smgrVersPTCHRom,smgrVersion(a0)
|
||
EndWith
|
||
ENDIF
|
||
|
||
;____________________________________________________________________________
|
||
; Initialize additional Script Manager vectors pke <5.4>
|
||
; Add CallInterface pke <5.9>
|
||
; Add NewSwapIcon (7.0 only, moved to ptch 39) pke <6.2>
|
||
|
||
IF doScriptMgrNewVectors AND (NOT installScriptMgrPtch27) THEN ; <42><50>
|
||
|
||
ROMSMgrCalcRect EQU $1E1C2
|
||
ROMSMgrInitFonts EQU $1E21C
|
||
ROMCallInterface EQU $1E3B0 ; <5.9>
|
||
|
||
With SMgrRecord
|
||
GetSMgrCore a0
|
||
leaRom ROMSMgrCalcRect,a1
|
||
move.l a1,sVectSMgrCalcRect(a0)
|
||
leaRom ROMSMgrInitFonts,a1
|
||
move.l a1,sVectSMgrInitFonts(a0)
|
||
leaRom ROMCallInterface,a1 ; <5.9>
|
||
move.l a1,sVectCallInterface(a0) ; <5.9>
|
||
EndWith
|
||
ENDIF
|
||
|
||
;____________________________________________________________________________ pke <5.7>
|
||
; Install Script Manager 7.0 extensions, ROM patches
|
||
; Moved these installs up if doScriptMgrForAUX is true. <90>
|
||
|
||
IF NOT doScriptMgrForAUX THEN ; <90>
|
||
|
||
IF installScriptMgrPtch39 THEN ; <50>
|
||
PtchInst 39 ; <42>
|
||
ENDIF
|
||
IF installScriptMgrPtch27 THEN ; <50>
|
||
PtchInst 27 ; <5.7>
|
||
ENDIF
|
||
|
||
ENDIF ; <90>
|
||
|
||
;____________________________________________________________________________ pke <7.8>
|
||
; Install patches for Script Manager routines InitDateCache, String2Date
|
||
|
||
IF doScriptMgrStr2DatFix AND (NOT installScriptMgrPtch39) THEN ; <42><50>
|
||
smInitDateCacheOff equ -16 ; DispTable offset for InitDateCache
|
||
smString2DateOff equ -20 ; DispTable offset for String2Date
|
||
|
||
With SMgrRecord
|
||
GetSMgrCore a1
|
||
move.l smgrDispTable(a1),a1
|
||
|
||
lea NewInitDateCache,a0
|
||
move.l a0,smInitDateCacheOff(a1)
|
||
lea NewString2Date,a0
|
||
move.l a0,smString2DateOff(a1)
|
||
|
||
EndWith
|
||
ENDIF
|
||
|
||
;____________________________________________________________________________ pke <8.0>
|
||
; Install Script Manager tail patch to _GetIndADB, fixes the way SwapKybd
|
||
; clears dead key state in ADB keyboard driver data structure
|
||
|
||
IF doScriptMgrRstKCHRFix AND (NOT installScriptMgrPtch39) THEN ; <42><50>
|
||
PatchOSJump oldGetIndADB,$78 ; set addr for BackToTrap
|
||
InstOSTp ptchGetIndADB,$78 ; Éand then install patch
|
||
ENDIF
|
||
|
||
|
||
;____________________________________________________________________________ pke <8.5>
|
||
; Install Script Manager patch to LwrString so it handles 2-byte chars
|
||
|
||
IF doScriptMgrLwrString2 AND (NOT installScriptMgrPtch27) THEN ; <8.5><50>
|
||
PatchOSJump oldLwrString,$56 ; set addr for BackToTrap
|
||
InstOSTp ptchLwrString,$56 ; Éand then install patch
|
||
ENDIF
|
||
|
||
;____________________________________________________________________________ EVA <7.1><123>
|
||
; Install Async Serial Driver Vector Address
|
||
Import SerialPatch
|
||
InstOSTp SerialPatch,$A0BE
|
||
|
||
SERDVersion equ 5
|
||
; install new version number
|
||
move.l #5*4,d0 ; first serial DCE is 5th entry in Utbl
|
||
moveq #4-1,d1 ; index through 4 dce's (adjusted for dbra)
|
||
@next movea.l UTableBase,a0 ; get ptr to the unit table
|
||
movea.l 0(a0,d0.w),a0 ; get DCE handle
|
||
movea.l (a0),a0 ; get DCE ptr
|
||
move.w #SERDVersion,dCtlQueue(a0) ; post new version
|
||
addq #4,d0 ; get next DCE
|
||
dbra d1,@next
|
||
|
||
|
||
;____________________________________________________________________________ GGD <8.4>
|
||
; Install ADB Polling patch for ViaADB implementations only
|
||
;
|
||
; If we are running on a machine with ViaADB (ie. No IOPs), then we allocate a
|
||
; block for this patch, copy the code into it, and install it (saving heap space
|
||
; on machines that don't need it).
|
||
;
|
||
; This patch changes Auto/SRQ polling to only poll device addresses which have entries
|
||
; in the device table.
|
||
|
||
OldFDBShiftInt equ $0000a700 ; ROM offset of old FDBShiftInt
|
||
SendByte2Rtn equ $0000A6D0 ; ROM offset of return from second @sendNextByte call
|
||
GetByte2Rtn equ $0000A63C ; ROM offset of return from second @getNextByte call
|
||
ROM@sendNextByte equ $0000A6E6 ; ROM offset of @sendNextByte label
|
||
ROM@fetchLoop equ $0000A63A ; ROM offset of @fetchLoop label
|
||
ROM@handleSRQ equ $0000A724 ; ROM offset of SRQ handling code
|
||
ROM@skipUpdate equ $0000A738 ; ROM offset of ReqDoneVIA exit without updating ADDR
|
||
|
||
InstallADBPollPatch
|
||
cmpRA OldFDBShiftInt,Lvl1dt+8 ; see if correct shift int handler to patch
|
||
bne.s @exit ; if not, don't patch it (might not be VIA based ADB)
|
||
|
||
lea ADBPollPatchStart,a1 ; get address of code to copy
|
||
move.l (a1),d0 ; length of code
|
||
_NewPtr ,SYS ; allocate space for the code
|
||
bne.s @exit ; if couldn't allocate, don't install it
|
||
|
||
move.l (a1)+,d0 ; length of code
|
||
exg.l a0,a1 ; setup src/dst for block move
|
||
_BlockMove ; copy the code
|
||
move.l a1,Lvl1DT+8 ; install new shift int handler
|
||
@exit bra.w ADBPollPatchEnd ; jump around patch body
|
||
|
||
|
||
ADBPollPatchStart
|
||
dc.l ADBPollPatchEnd-ADBPollPatchStart-4
|
||
with ADBVars
|
||
;_______________________________________________________________________
|
||
; Routine: FDBShiftInt
|
||
; Inputs: A1 - base address of VIA1 (setup by IntHnd)
|
||
; Outputs: A1 - base address of VIA1
|
||
; A3 - pointer to ADBBase
|
||
; ccr.z - result of BTST #vFDBInt,vBufB(a1)
|
||
;
|
||
; Function: handles shift interrupt, resumes asynchronous processing
|
||
;_______________________________________________________________________
|
||
|
||
FDBShiftInt movea.l ADBBase,a3 ; point to ADB globals in low memory
|
||
movea.l ShiftIntResume(a3),a0 ; get address to resume at
|
||
cmpRA SendByte2Rtn,a0 ; see if resuming from sending second byte
|
||
beq.s SendPatch ; if so, use the patched code
|
||
cmpRA GetByte2Rtn,a0 ; see if resuming from fetching second byte
|
||
beq.s FetchPatch ; if so, use the patched code
|
||
btst.b #vFDBInt,vBufB(a1) ; test the FDBInt~ status
|
||
jmp (a0) ; resume async processing
|
||
|
||
|
||
SendPatch btst.b #vFDBInt,vBufB(a1) ; test the FDBInt~ status
|
||
bne.s @sendLoop ; if no SRQ, send the data
|
||
bset.b #fDBSRQ,FDBAuFlag(a3) ; remember that a service request was returned
|
||
|
||
@sendLoop tst.b fDBCnt(a3) ; see if end of buffer reached
|
||
beq.s ReqDoneVIA ; leave when count is zero, no reply data
|
||
jsrROM ROM@sendNextByte ; send another byte
|
||
bra.s @sendLoop ; loop until count exhausted
|
||
|
||
|
||
FetchPatch btst.b #vFDBInt,vBufB(a1) ; test the FDBInt~ status
|
||
beq.s @fetchDone ; exit if end of data reached
|
||
cmpi.b #8,fDBCnt(a3) ; see if end of buffer reached
|
||
bhs.s @fetchDone ; keep fetching until end of data
|
||
jmpROM ROM@fetchLoop
|
||
@fetchDone btst.b #fDBNoReply,FDBAuFlag(a3) ; see if buffer data is valid
|
||
seq.b d0 ; $FF if data is valid, $00 if no reply
|
||
and.b d0,fDBCnt(a3) ; set count to zero if timeout
|
||
* bra.s ReqDoneVIA
|
||
|
||
|
||
ReqDoneVIA move.b FDBAuFlag(a3),d0 ; get the flags
|
||
move.b fDBCmd(a3),d1 ; get the command
|
||
moveq.l #(1<<fDBSRQ),d3 ; mask to test for SRQ pending
|
||
and.b d0,d3 ; isolate the bit
|
||
neg.l d3 ; set bit 31 if SRQ pending
|
||
move.b d1,d3 ; insert the command byte
|
||
|
||
lsr.b #4,d1 ; isolate the device address
|
||
tst.l d3 ; was there an SRQ?
|
||
bpl.s @noSRQ ; if not, don't advance poll address
|
||
jmpROM ROM@handleSRQ ; otherwise, go handle the SRQ
|
||
@noSRQ move.w DevMap(a3),d2 ; list of possible address to search
|
||
btst.l d1,d2 ; see if it is in the table
|
||
beq.s @skipUpdate ; if not, don't switch to that address
|
||
move.b d1,PollAddr(a3) ; remember where to auto/SRQ poll next
|
||
@skipUpdate jmpROM ROM@skipUpdate ; back to ROM, just past the update
|
||
ADBPollPatchEnd
|
||
|
||
; End of ADB Polling patch for ViaADB implementations
|
||
;____________________________________________________________________________ GGD <8.4>
|
||
|
||
|
||
;____________________________________________________________________________ GGD <8.4>
|
||
; Install a Time Manager Task to simulate the 60.15Hz pseudo VBL for OSS based systems.
|
||
;
|
||
; If we are running on a machine with an OSS, then we allocate a block for this patch,
|
||
; copy the code into it, and install it (saving heap space on machines that don't need it).
|
||
;
|
||
; This patch corrects the pseudo VBL frequency on OSS based systems, the OSS generates
|
||
; a 60.00Hz interrupt, but the Macintosh Pseudo VBL rate should be 60.14742 Hz.
|
||
; To correct this, we simply ignore and disable the OSS interrupt, and use the
|
||
; Time Manager to generate interrupts at the correct rate.
|
||
|
||
FixMPWShell equ 1 ; Temporarily fix CMD-Period <25>
|
||
; This same patch is also modified to fix a problem in the MPW Shell on Zone-5.
|
||
; The real bug is in the MPW Shell, but we will temporarily fix it here until they
|
||
; have a chance to rev, so that we don't hear bitching from developers.
|
||
; The MPW Shell will sometimes cut back the stack from within a patch they make to
|
||
; PostEvent, when CMD-Period is pressed. Therefore, it may never return back to the
|
||
; keyboard driver, which never returns to the ADBManager, which never returns to the
|
||
; IOP Manager, which never returns to the Deferred Task Manager, which never returns
|
||
; to the Interrupt Handler, which never returns to whatever code was running at the
|
||
; time of the interrupt (which may have been another interrupt). This causes data
|
||
; structures to be left in inconsistent states, such as the deferred task manager thinks
|
||
; that a deferred task is still running, and won't run any new tasks.
|
||
; The work around is to not run ADB as a deferred task, and instead run it at level 1 <25>
|
||
|
||
ROMLevel1OSSInt equ $00009B50 ; ROM offset of old Level1OSSInt
|
||
ServiceIntMMU equ $00009B68 ; ROM offset of ServiceIntMMU
|
||
if FixMPWShell then ; <25>
|
||
IOPInterrupt equ $00005036 ; ROM offset of IOP Manager interrupt handler <25>
|
||
ContinueOssLevel1Decode equ $00009D8E ; ROM offset of continuation of OssLevel1Decode <25>
|
||
else ; <25>
|
||
ContinueOssLevel1Decode equ $00009D88 ; ROM offset of continuation of OssLevel1Decode
|
||
endif ; <25>
|
||
OssVBL60HzInt equ $00009DF0 ; ROM offset of OssVBL60HzInt
|
||
|
||
IntRegs reg a0-a3/d0-d3 ; registers saved by all interrupt handlers
|
||
|
||
bra.s Oss60HzPatchEnd ; skip over patch body into install code
|
||
|
||
Oss60HzPatchStart
|
||
|
||
Oss60HzTimeHandler
|
||
movea.l a1,a0 ; point to the TMTask
|
||
move.l #-16626,d0 ; 16.626 ms, 60.14742 Hz (pseudo VBL rate)
|
||
movea.l jPrimeTime,a1 ; point to the routine
|
||
jsr (a1) ; initiate the delay
|
||
movea.l OSS,a1 ; get OSS chip base address
|
||
jmpROM OssVBL60HzInt ; run the VBL interrupt
|
||
|
||
OssLevel1Decode
|
||
movea.l OSS,a1 ; get OSS chip base address
|
||
move.w OSSIntStat(a1),d0 ; see who is interrupting
|
||
bclr.l #OSSIntVBL60Hz,d0 ; ignore OSS 60Hz pseudo VBL interrupt
|
||
if FixMPWShell then ; <25>
|
||
btst #OSSIntIOPSWIM,d0 ; check SWIM IOP first <25>
|
||
beq.s OSSPSwmMasked ; if no SWIM IOP Interrupt, skip it <25>
|
||
moveq.l #7,d1 ; mask for int level <25>
|
||
and.b OSSMskPSwm(a1),d1 ; see if SWIM IOP was disabled <25>
|
||
beq.s OSSPSwmMasked ; if disabled, ignore it <25>
|
||
move.l #(%00001000<<24)+\ ; allow xmt msg 3 (ADB) <25>
|
||
(%00001000<<16)+\ ; allow rcv msg 3 (ADB) <25>
|
||
(0<<8)+\ ; this byte must be zero <25>
|
||
1,d0 ; ADB is on SWIM IOP (IOP 1) <25>
|
||
jmpROM IOPInterrupt ; handle the interrupt and return <25>
|
||
OSSPSwmMasked ; <25>
|
||
endif ; <25>
|
||
jmpROM ContinueOssLevel1Decode ; resume with the ROM code
|
||
|
||
|
||
Level1OSSInt
|
||
movem.l IntRegs,-(SP) ; preserve registers
|
||
lea OssLevel1Decode,a3 ; use the OSS level 1 dispatcher
|
||
jmpROM ServiceIntMMU ; call primary interrupt dispatcher
|
||
|
||
Oss60HzPatchEnd
|
||
@PatchSize equ Oss60HzPatchEnd-Oss60HzPatchStart
|
||
|
||
cmpRA ROMLevel1OSSInt,AutoInt1; see if we have an OSS interrupt handler
|
||
bne.s @done ; if not, don't need to install it
|
||
|
||
moveq.l #tmXQSize+@PatchSize,d0 ; space needed
|
||
_NewPtr ,Sys,Clear ; allocate it
|
||
bne.s @done ; if can't allocate, don't install
|
||
movea.l a0,a2 ; save a copy
|
||
lea Oss60HzPatchStart,a0 ; source address
|
||
lea tmXQSize(a2),a1 ; dest address
|
||
moveq.l #@PatchSize,d0 ; byte count
|
||
_BlockMove ; copy the code
|
||
|
||
lea Oss60HzTimeHandler-Oss60HzPatchStart(a1),a0 ; point to the handler
|
||
move.l a0,tmAddr(a2) ; initialize the task address
|
||
movea.l a2,a0 ; get the time manager task address
|
||
move.l #'eada',(a0) ; put in magic signature (see VM for details) <139>
|
||
_InsXTime ; install the task (fixed frequency)
|
||
|
||
move.l #-16626,d0 ; 60.14742 Hz (pseudo VBL rate)
|
||
movea.l jPrimeTime,a2 ; point to the routine
|
||
lea Level1OSSInt-Oss60HzPatchStart(a1),a1
|
||
|
||
move.l Ticks,d1 ; get the current time
|
||
@sync cmp.l Ticks,d1 ; sync with the VBL manager
|
||
beq.s @sync ; wait for it to change
|
||
|
||
move.w sr,-(sp) ; save old int level
|
||
ori.w #HiIntMask,sr ; disable all ints
|
||
|
||
move.l a1,AutoInt1 ; install the new level 1 handler
|
||
|
||
movea.l OSS,a1 ; get the OSS base
|
||
clr.b OSSMsk60Hz(a1) ; disable the OSS 60Hz interrupt source
|
||
move.w (sp)+,sr ; restore the interrupt level
|
||
|
||
jsr (a2) ; start the pseudo VBL timer
|
||
@done
|
||
|
||
; End of OSS VBL frequency patch
|
||
;____________________________________________________________________________ GGD <8.4>
|
||
|
||
|
||
;____________________________________________________________________________ SWC <8.8>
|
||
; RecoverHandle() patch for 32-bit Memory Manager
|
||
|
||
IMPORT v24RecoverHandle,v32RecoverHandle
|
||
|
||
JRecoverHandle EQU $6C ;offset into 32-bit Memory Manager's vector table
|
||
|
||
LEA v24RecoverHandle,A0 ;patch in the 24-bit version of RecoverHandle
|
||
MOVE.L A0,JMemMgr24+JRecoverHandle
|
||
LEA v32RecoverHandle,A0 ;patch in the 32-bit version of RecoverHandle
|
||
MOVE.L A0,JMemMgr32+JRecoverHandle
|
||
|
||
; End of RecoverHandle() patch install
|
||
;____________________________________________________________________________ SWC <8.8>
|
||
|
||
|
||
;____________________________________________________________________________ RMP <12>
|
||
; SetHandleSize() patch for 32-bit Memory Manager
|
||
|
||
IMPORT v32SetHandleSize
|
||
|
||
JSetHandleSize EQU $64 ;offset into 32-bit Memory Manager's vector table
|
||
|
||
LEA v32SetHandleSize,A0 ;patch in the 32-bit version of SetHandleSize
|
||
MOVE.L A0,JMemMgr32+JSetHandleSize
|
||
|
||
|
||
; End of SetHandleSize() patch install
|
||
;____________________________________________________________________________ RMP <12>
|
||
|
||
|
||
|
||
;____________________________________________________________________________ CSL
|
||
; SetPtrSize() patch for 32-bit Memory Manager
|
||
|
||
IMPORT v32SetPtrSize
|
||
|
||
JSetPtrSize EQU $4C ;offset into 32-bit Memory Manager's vector table
|
||
|
||
LEA v32SetPtrSize,A0 ;patch in the 32-bit version of SetPtrSize
|
||
MOVE.L A0,JMemMgr32+JSetPtrSize
|
||
|
||
|
||
; End of SetPtrSize() patch install
|
||
;____________________________________________________________________________ CSL
|
||
|
||
IF 0 THEN
|
||
;____________________________________________________________________________ jwk <19>
|
||
;
|
||
; Patch in FastReadOSS() and FastWriteOSS() ROM routines to use the SCSIDMA chip.
|
||
;
|
||
WITH ROMHeader, scsiGlobalRecord
|
||
|
||
ROMFastWriteOSS EQU $00009042
|
||
ROMFastReadOSS EQU $000092ea
|
||
|
||
cmpi.b #boxF19,BoxFlag ; is it an F19 ?
|
||
bne.s @jwkNoInstall ; only applies to F19's
|
||
move.w #$11f0,d0 ; check for any final F19 ROM
|
||
movea.l ROMBase,a1 ; point to the base of the ROM
|
||
and.w ROMRelease(a1),d0 ; we'll take 1.1f1, 1.1f2, etc.
|
||
cmpi.w #$11f0,d0 ; is it a 1.1fÉ ROM ?
|
||
bne.s @jwkNoInstall ; only install on a Zone5 with 1.1fÉ ROM's
|
||
|
||
; <57> 04-22-90 csd
|
||
; commented out the installation of SCSI DMA so we stop trashing
|
||
; hard disks on the IIfx.
|
||
|
||
movea.l SCSIGlobals,a1 ; point to SCSI Manager globals
|
||
move.l #250*10000,G_Reserved1(a1) ; set up 250ms byte-to-byte timeout
|
||
leaROM ROMFastWriteOSS,a0
|
||
; move.l a0,jvVFWO(a1) ; use DMA code for SCSIWBlind
|
||
leaROM ROMFastReadOSS,a0
|
||
; move.l a0,jvVFRO(a1) ; use DMA code for SCSIRBlind
|
||
@jwkNoInstall
|
||
|
||
ENDWITH
|
||
;
|
||
; End of FastReadOSS() and FastWriteOSS() patch install
|
||
;____________________________________________________________________________ jwk <19>
|
||
ENDIF
|
||
|
||
;____________________________________________________________________________ jwk <29>
|
||
;
|
||
; Patch in chaining SCSI bus error handler
|
||
;
|
||
TestFor SCSI96_1Exists ; check universal tables for C96 SCSI Chip <3>
|
||
bne.s @ChaningBErrDone ; has C96 - do not install patch (or die) <3>
|
||
|
||
WITH scsiGlobalRecord
|
||
|
||
movea.l SCSIGlobals,a1 ; point to SCSI Manager globals
|
||
lea.l BusErrHandler,a0 ; point to bus error handler patch
|
||
move.l a0,jvBusErr(a1) ; patch vector in the globals
|
||
|
||
ENDWITH
|
||
@ChaningBErrDone
|
||
|
||
;_________________________________________________________________________________________ <119> djw
|
||
; Install SCSI fix for Quantum 7.9 rom fix
|
||
|
||
with scsiGlobalRecord
|
||
|
||
; Check the universal tables in this ROM version for a SCSI DMA chip (the GDU). If
|
||
; the GDU exist, then we must be on a Mac IIfx (dammed overpatch ROM's). The Quantum
|
||
; fix cannot be applied to the IIfx because on the GDU, *ACK cannot be controlled.
|
||
|
||
TestFor SCSIDMAExists ; check universal tables for SCSI DMA
|
||
bne.s @noSCSIpatch ; has SCSI DMA - do not install patch
|
||
|
||
TestFor SCSI96_1Exists ; check universal tables for C96 SCSI Chip <136>
|
||
bne.s @noSCSIpatch ; has C96 - do not install patch (or die) <136>
|
||
|
||
; Apply the patch to this Mac IIci family ROM
|
||
|
||
lea QuantumWBlindIIci,a0 ; a0 = TIB interpreter patch
|
||
move.l a0,jvWBlind(a1) ; replace vector
|
||
|
||
lea FastWriteFix,a0 ; patch to FastWrite data xfer routine
|
||
move.l a0,jvVFWO(a1) ; virtual fast writes (hhsk)
|
||
move.l a0,jvVFW(a1) ; virtual fast writes (hhsk)
|
||
@noSCSIpatch
|
||
|
||
;_________________________________________________________________________________________ <122> djw
|
||
; Install SCSIDispatch patch for VM conflict
|
||
;
|
||
; Patch SCSIDispatch back to ROM to avoid the situation where VM patches SCSIDispatch
|
||
; before patches, and after patches. VM will be in the chain of patches twice. This
|
||
; coupled with the SCSI mgr calling the file system gets into a circular calling sequence
|
||
; of the SCSI mgr calling VM and VM calling the SCSI mgr.
|
||
|
||
@ROMSCSIDispatch Equ $00007460 ; offset to SCSIDispatch in ROM
|
||
|
||
movea.l RomBase,a0 ; get base of ROM
|
||
adda.l #@ROMSCSIDispatch,a0 ; add offset to SCSIDispatch in ROM
|
||
setTrapA0 $a815 ; patch SCSIDispatch to ROM
|
||
|
||
;____________________________________________________________________________
|
||
;
|
||
; <54> Install patch to IOPMsgRequest to fix IOP Serial Driver Ctrl Call bug
|
||
;____________________________________________________________________________
|
||
IMPORT IOPMsgRequest
|
||
|
||
move.w sr, -(sp) ; disable interrupts while we patch
|
||
ori.w #HiIntMask,sr
|
||
|
||
;
|
||
; Install the patch only if IOPMsgRequest trap already exists
|
||
;
|
||
gettrapA0 $A087 ; get IOPMsgRequest trap addr
|
||
move.l a0,a1 ; set it aside
|
||
gettrapA0 $A89F ; get unimplemented trap addr
|
||
cmpa.l a0,a1 ; check 'em
|
||
beq.s @noTrap ; nope, so don't install patch
|
||
|
||
PatchOSJump oldIOPMsgRequest,$87 ; Stash original IOPMsgRequest routine <12>
|
||
InstOSTp IOPMsgRequest,$87 ; replace IOPMsgRequest trap <12>
|
||
@noTrap
|
||
|
||
; restore state
|
||
move.w (sp)+,sr ; disable interrupts while we patch
|
||
|
||
;____________________________________________________________________________
|
||
;
|
||
; <54> End Install patch to IOPMsgRequest to fix IOP Serial Driver Ctrl Call bug
|
||
;____________________________________________________________________________
|
||
|
||
|
||
;____________________________________________________________________________ GGD <28>
|
||
; Patch the Deferred Task Manager Task Dispatcher to re-enable interrupts upon
|
||
; exiting to fix QuickMail servers (for now at least), because they call through
|
||
; jDisptch at application level and wind up with all interrupts being masked,
|
||
; and the Task Dispatcher expects to only be called from then end of an interrupt
|
||
; handler, which will restore the interrupt level via an RTE.
|
||
|
||
PatchOSJump ROMvDisptch,$B9 ; set addr for BackToTrap
|
||
InstOSTp NewvDisptch,$B9 ; Éand then install patch
|
||
|
||
; End of Deferred Task Manager Task Dispatcher Patch Installation
|
||
;____________________________________________________________________________ GGD <28>
|
||
|
||
;____________________________________________________________________________ EH <4>
|
||
; Patch the secondary dispatcher for the Level 4 IOP interrupt handler
|
||
;
|
||
; This patch fixes some of the serial thruput problems encountered on Apollo
|
||
; and the TimLC when the CPUs are running in 24 bit mode. These are the first (slow)
|
||
; machines to run in 32 bit mode a good portion of the time. Every time we
|
||
; take an interrupt the primary interrupt handler switches the CPU into 24 bit
|
||
; mode, forcing cache flushes and generally incurring a lot of overhead. At high
|
||
; serial baud rates, this overhead interferes with our ability to keep pace.
|
||
;
|
||
; The solution is to NOT take an interrupt for each received character, but
|
||
; rather to empty out the SCC FIFO before returning to the primary interrupt
|
||
; dispatch. So we patch the secondary dispatcher to call the serial driver's
|
||
; interrupt routines, rather than jumping to them. The service routine then
|
||
; returns to the secondary dispatcher, with checks to see if there is another
|
||
; character available on either port. If there is another character pending,
|
||
; the secondary dispatch routine loops to dispatch to the new interrupt (that
|
||
; must be pending) rather than returning to the primary dispatcher (and incurring
|
||
; the overhead).
|
||
;
|
||
; we do this ONLY FOR CHANNEL A, since it's the only one that's documented to be
|
||
; fast, and also so that appletalk won't pound us at its 230Kbaud rate.
|
||
;
|
||
; The Serial Driver Rx and SC interrupt service routines are patched in conjuction
|
||
; with this so that if a device manager request completes, we exit to the primary
|
||
; dispatcher regardless of whether a character is pending. This way we exit the
|
||
; interrupt handlers completely at least once per device manager request, allowing
|
||
; things like deferred tasks to run more in sequence.
|
||
;
|
||
; <6> fix the Farallon MacRecorder bug
|
||
; modified patch to test for port A RxChar and loop back only if we are servicing
|
||
; a channel A interrupt. For port B we just jump to service routine like ROM code.
|
||
;
|
||
; <7> fix patch <6>
|
||
; Port B dispatcher fixed to call serial service routines and to have same number
|
||
; of bytes before the rts so that async serial driver Rx and SCx patches (which
|
||
; fiddle with return address on stack) return to the proper place.
|
||
;
|
||
; <10> for VM, patch level 4 autovector pointed to by vbr, not just the zero-offset.
|
||
|
||
|
||
ROMLevel4SccInt equ $00009b20 ; ROM offset of old SCCIOPBypassInt
|
||
IntRegsSize equ 8*4 ; size of IntRegs in bytes, must change if IntRegs changes
|
||
SccDT equ Lvl2DT ; Dispatch table for SCC interrupts
|
||
|
||
bra.s SCCPatchEnd ; branch to install code
|
||
SCCPatchStart
|
||
|
||
;
|
||
; this is the secondary dispatcher code we are patching
|
||
;
|
||
SCCIOPBypassInt
|
||
SccDecode MOVE.L SCCRd,A0 ; get SCC read address
|
||
MOVE.B (A0),D0 ; read to sync up SCC (just to be safe)
|
||
MOVE.L SCCWr,A1 ; get SCC channel B write control address
|
||
SccDecodeCommon
|
||
MOVE.B #2,(A1) ; point to SCC register 2, B channel
|
||
LEA SccDT,A2 ; point to dispatch table and delay
|
||
MOVEQ #$0E,D0 ; 'and mask' and extra delay
|
||
AND.B (A0),D0 ; read the modified interrupt vector
|
||
CMPI.B #8,D0 ; channel A interrupt?
|
||
|
||
bge.S @GoChannelA ; branch if for A <6>
|
||
MOVE.L 0(A2,D0.W*2),A2 ; get dispatch vector <6>
|
||
jsr (A2) ; call service routine <6> <7>
|
||
bra.s @fixedRTS ; fill in the 10 bytes as for port A <7>
|
||
dcb.b 8,0 ; so that Rx,SCx handlers return properly <7>
|
||
@fixedRTS rts
|
||
|
||
@GoChannelA ; <6>
|
||
ADDQ #2,A0 ; adjust SCC addresses for port A
|
||
ADDQ #2,A1
|
||
@GoLvl2
|
||
MOVE.L 0(A2,D0.W*2),A2 ; get dispatch vector
|
||
jsr (A2) ; call service routine <6>
|
||
; note we return here UNLESS we finish a device manager request
|
||
; note this is 10 bytes-- CHANGE THE SCC RxIntHnd patch equate if this changes!!!!!
|
||
movea.l SCCRd,a0 ; point to SCC read base address <6>
|
||
btst.b #RxCA,2(a0) ; SCC data available on channel A? <6>
|
||
bne.s SCCDecode ; data available, so dispatch again <6>
|
||
; note we return here if we are finishing a device manager request
|
||
rts ; return to primary dispatcher <6>
|
||
|
||
SCCIOPBypassIntEnd ; for IOP patch below <7>
|
||
SCCIOPBypassIntSize equ SCCIOPBypassIntEnd-SCCIOPBypassInt; <7>
|
||
;
|
||
;
|
||
; this is the primary dispatch code we patch in order to get to the secondary dispatcher
|
||
;
|
||
Level4SccInt
|
||
movem.l IntRegs,-(SP) ; preserve registers
|
||
lea SCCIOPBypassInt,a3 ; use the SCC IOP interrupt dispatcher
|
||
jmpROM ServiceIntMMU ; call primary interrupt dispatcher
|
||
|
||
SccPatchEnd
|
||
@SccPatchSize equ SccPatchEnd-SccPatchStart
|
||
|
||
;
|
||
; this is the install code for the patch
|
||
;
|
||
cmpRA ROMLevel4SccInt,AutoInt4 ; see if we have an SCC bypass interrupt handler
|
||
bne.s @done ; if not, don't need to install it
|
||
|
||
moveq.l #@SccPatchSize,d0 ; space needed
|
||
_NewPtr ,Sys,Clear ; allocate it
|
||
bne.s @done ; if can't allocate, don't install
|
||
movea.l a0,a1 ; dest address
|
||
lea SccPatchStart,a0 ; source address
|
||
moveq.l #@SccPatchSize,d0 ; byte count
|
||
_BlockMove ; copy the code
|
||
|
||
move.w sr,-(sp) ; save old int level
|
||
ori.w #HiIntMask,sr ; disable all ints
|
||
lea Level4SccInt-SccPatchStart(a1),a1 ; get offset to primary dispatcher code
|
||
move.l a1,AutoInt4 ; install the new level 4 handler
|
||
movec vbr,a0 ; get the vbr in case VM moved it <10>
|
||
move.l a1,AutoInt4(a0) ; install the new level 4 handler <10>
|
||
move.w (sp)+,sr ; restore the interrupt level
|
||
@done
|
||
|
||
; End of Lvl4Int secondary dispatcher patch
|
||
;____________________________________________________________________________ EH <4>
|
||
|
||
;____________________________________________________________________________ EH <30>
|
||
; Patch the SCCIOP interrupt handler to set all completion flags to immediate.
|
||
;
|
||
; If we are running on a machine with an OSS, then we allocate a block for this patch,
|
||
; copy the code into it, and install it (saving heap space on machines that don't need it).
|
||
;
|
||
; This patch fixes things so that TIMBUKTU/REMOTE, slime code that it is, will
|
||
; run on a Zone 5 in IOP mode. Timbuktu/Remote makes SYNCHRONOUS read calls to
|
||
; the IOP Serial driver FROM A VBL TASK. Sometimes the VBL gets called when the
|
||
; IOP Manager completion routine (for a call from the serial driver) is waiting
|
||
; to run (as a deferred task).
|
||
; The result is that the synchronous call waits in the Device Manager for IODone
|
||
; to be called, but IODone is called by the serial driver, which is returned to
|
||
; from the IOP Manager completion routine, which is NEVER returned to because we
|
||
; made a synchronous call from an elevated interrupt level and are now just sitting
|
||
; in a loop in the device manager: DEADLOCK.
|
||
;
|
||
; The reason Timbuktu/Remote worked on previous Macs is that the bypass driver
|
||
; does NOT use a deferred task to call IODone.
|
||
;
|
||
; The work around is to not call the IOP Manager completion routines for the SCC
|
||
; as deferred tasks, but instead call them at level 1 (immediately).
|
||
;
|
||
; <10> for VM, patch level 4 autovector pointed to by vbr, not just the zero-offset.
|
||
|
||
ROMLevel4SccIopInt equ $00009B10 ; ROM offset of old Level4SccIopInt
|
||
|
||
bra.s SccIopPatchEnd ; skip over patch body into install code
|
||
|
||
SCCIopPatchStart
|
||
SCCIopInt
|
||
move.l #(%11111111<<24)+\ ; complete xmt msgs 0..7 immediate
|
||
(%11111111<<16)+\ ; complete rcv msg 0..7 immediate
|
||
(0<<8)+\ ; this byte must be zero
|
||
0,d0 ; SCC IOP number 0
|
||
jmpROM IOPInterrupt ; handle the interrupt and return
|
||
|
||
Level4SccIopInt
|
||
movem.l IntRegs,-(SP) ; preserve registers
|
||
lea SccIopInt,a3 ; use the SCC IOP interrupt dispatcher
|
||
jmpROM ServiceIntMMU ; call primary interrupt dispatcher
|
||
|
||
SccIopPatchEnd
|
||
@SccIopPatchSize equ SccIopPatchEnd-SccIopPatchStart
|
||
|
||
|
||
cmpRA ROMLevel4SccIopInt,AutoInt4; see if we have an SCC IOP interrupt handler
|
||
bne.s @done ; if not, don't need to install it
|
||
|
||
moveq.l #@SccIopPatchSize,d0 ; space needed
|
||
_NewPtr ,Sys,Clear ; allocate it
|
||
bne.s @done ; if can't allocate, don't install
|
||
movea.l a0,a1 ; dest address
|
||
movea.l a0,a2 ; save dest addr <7>
|
||
lea SccIopPatchStart,a0 ; source address
|
||
moveq.l #@SccIopPatchSize,d0 ; byte count
|
||
_BlockMove ; copy the code
|
||
|
||
;patch the bypass interrupt handler
|
||
moveq.l #SCCIOPBypassIntSize,d0 ; space needed
|
||
_NewPtr ,Sys,Clear ; allocate it
|
||
bne.s @done ; if can't allocate, don't install
|
||
movea.l a0,a1 ; dest address
|
||
lea SCCIOPBypassInt,a0 ; source address
|
||
moveq.l #SCCIOPBypassIntSize,d0 ; byte count
|
||
_BlockMove ; copy the code
|
||
|
||
; install the patches
|
||
move.w sr,-(sp) ; save old int level
|
||
ori.w #HiIntMask,sr ; disable all ints
|
||
|
||
movea.l IOPmgrVars,a0 ; get IOP mgr globals <7>
|
||
move.w #SccIopNum,d0 ; get SCC IOP number as index <7>
|
||
; fortunately the IOPInfoPtrs are declared at offset zero to IOPMgrVars <7>
|
||
; as shown here below <7>
|
||
; IOPMgrGlobals record {IOPInfoPtrs},increment ; globals used by the IOP manager <7>
|
||
move.l (a0,d0.w*4),d0 ; get SCCIOP info pointer <7>
|
||
move.l d0,a0 ; <7>
|
||
with IOPInfo ; <7>
|
||
move.l a1,BypassHandler(a0) ; a1-> secondary SCC dispatcher <7>
|
||
endwith ; <7>
|
||
|
||
lea Level4SccIOPInt-SccIopPatchStart(a2),a1 ;a2-> primary handler <7>
|
||
move.l a1,AutoInt4 ; install the new level 4 handler
|
||
movec vbr,a0 ; get the vbr in case VM moved it <10>
|
||
move.l a1,AutoInt4(a0) ; install the new level 4 handler <10>
|
||
move.w (sp)+,sr ; restore the interrupt level
|
||
|
||
@done
|
||
|
||
; End of SccIopInt patch
|
||
;____________________________________________________________________________ EH <30>
|
||
|
||
;____________________________________________________________________________ EH <33>
|
||
;
|
||
; Install patch to IOPMoveData to fix IOP Serial Driver DMA Hang bug
|
||
;
|
||
IMPORT IOPMoveData
|
||
;save state
|
||
move.w sr, -(sp) ; disable interrupts while we patch
|
||
ori.w #HiIntMask,sr
|
||
movem.l a0/d0-d1,-(sp) ; save some registers
|
||
|
||
; Install patch only if IOPMoveData trap already exists
|
||
clr.l d0 ; clear result
|
||
move.w #UnimplementedTrap,d0 ; get loc of unimplemented trap
|
||
_GetTrapAddress ,newTool ; get the address into A0
|
||
move.l a0,d1 ; save it for a sec
|
||
move.l #$A088,d0 ; trap ID to check for IOPMoveData
|
||
_GetTrapAddress ,NewOS ; get the address of it
|
||
cmp.l a0,d1 ; is it implemented?
|
||
beq.s @noTrap ; nope, so don't install patch
|
||
|
||
|
||
PatchOSJump oldIOPMoveData,$88 ; set addr for BackToTrap
|
||
InstOSTp IOPMoveData,$88 ; implemented, so install new trap addr
|
||
|
||
@noTrap
|
||
|
||
; restore state
|
||
movem.l (sp)+,a0/d0-d1 ; restore saved registers
|
||
move.w (sp)+,sr ; disable interrupts while we patch
|
||
|
||
;
|
||
;
|
||
; End Install patch to IOPMoveData to fix IOP Serial Driver DMA Hang bug
|
||
;____________________________________________________________________________ EH <33>
|
||
|
||
|
||
;____________________________________________________________________________ <10> <cch 8/6/91>
|
||
;
|
||
; Install patch to getPageDesc and _VM. These patches take effect only on
|
||
; 68030 machines with the Terror ROM, version $67c, sub-version 1.5 when VM
|
||
; is disabled.
|
||
;
|
||
ROMVers EQU $08
|
||
ROMSubVers EQU $12
|
||
VMGlobals EQU $b78
|
||
|
||
IMPORT GetPageDescPatch
|
||
|
||
; check to see if we're on the Terror ROM, subversion 1.5.
|
||
|
||
cmp.b #cpu68030,CPUFlag ; check if we're on an 030
|
||
bne.s @skipPatch ; ignore if not
|
||
move.l RomBase,a0 ; get base of ROM
|
||
cmp.w #TERRORmajorVers,ROMVers(a0); check major version
|
||
bne.s @skipPatch ; ignore if incorrect version
|
||
cmp.b #TERRORminorVers,ROMSubvers(a0); check subversion
|
||
bne.s @skipPatch ; ignore if incorrect version
|
||
tst.l VMGlobals ; check if VM is running
|
||
bpl.s @skipPatch ; ignore if VM is on
|
||
|
||
; patch _Gestalt
|
||
PatchOSJump origGestalt,$AD ; set addr for BackToTrap to orig _Gestalt
|
||
InstOSTp GetPageDescPatch,$AD ; implemented, so install new trap addr
|
||
|
||
PatchOSJump origMemDisp,$5C ; set addr for JsrTrap back to orig _VM
|
||
PatchOSJump origMemDisp1,$5C ; set addr for BackToTrap back to orig _VM
|
||
InstOSTp MemDispPatch,$5C ; implemented, so install new trap addr
|
||
|
||
@skipPatch
|
||
;
|
||
;
|
||
; End Install patch to getPageDesc proc
|
||
;____________________________________________________________________________ <10> <cch 8/6/91>
|
||
|
||
|
||
;____________________________________________________________________________ <13> <cch 8/28/91>
|
||
;
|
||
; Install patch to flush after backpatching fp68k calls made from ROM on
|
||
; 68030 running Terror.
|
||
;
|
||
FP68kPatchInstall
|
||
; check to see if we're on the Terror ROM, subversion 1.5.
|
||
cmp.b #cpu68030,CPUFlag ; check if we're on an 030
|
||
bne.s @skipPatch ; ignore if not
|
||
move.l RomBase,a0 ; get base of ROM
|
||
cmp.w #TERRORmajorVers,ROMVers(a0) ; check major version
|
||
bne.s @skipPatch ; ignore if incorrect version
|
||
cmp.b #TERRORminorVers,ROMSubvers(a0) ; check subversion
|
||
bne.s @skipPatch ; ignore if incorrect version
|
||
|
||
MOVE.W HwCfgFlags,D0 ; Get them Hardware Config Flags <14> SAM
|
||
BTST.L #hwCbFPU,D0 ; Does we gots an FPU? <14>
|
||
BEQ.S @skipPatch ; -> No, don't patch <14>
|
||
|
||
; patch _FP68k ($A9EB)
|
||
PatchToolJump origFP68k,$1EB ; set addr for BackToTrap to orig _Gestalt
|
||
InstToolTp FP68kPatch,$1EB ; implemented, so install new trap addr
|
||
|
||
@skipPatch
|
||
;
|
||
;
|
||
; End Install patch to fp68k
|
||
;____________________________________________________________________________ <13> <cch 8/28/91>
|
||
|
||
EndMacSection
|
||
;=========================================================================================
|
||
;=========================================================================================
|
||
;= =
|
||
;= END OF MAC-ONLY INSTALL CODE SECTION =
|
||
;= =
|
||
;=========================================================================================
|
||
;=========================================================================================
|
||
|
||
skipMacOnlyPatches ; above code is for Mac OS only
|
||
|
||
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
||
;############################### END PATCH INSTALL CODE #################################
|
||
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
||
|
||
CalcPatchSize
|
||
Lea StartPatch,A1 ; start of patch code
|
||
Lea EndOfPatch,A0 ; end of patch code
|
||
Sub.l A1,A0 ; calc size of resident code
|
||
Move.l A0,D0 ; SetHandleSize takes new size in D0
|
||
Move.l (SP)+,A0 ; restore the handle passed by SysPatch
|
||
|
||
Bra CutBack ; go cut the install code off and exit
|
||
|
||
ENDPROC
|
||
|
||
UsesPtchInst ; Patchinstll code Macro <1.1-4april89-CEL>
|
||
|
||
; added Proc FixupTbl from PatchIIROM.a <24July89smb>
|
||
Proc
|
||
Export FixupTbl
|
||
|
||
;################## TABLE OF LOCATIONS TO BE OFFSET BY [ROMBase] ####################
|
||
;
|
||
; Table contains one entry for each reference to a ROM address from the
|
||
; JmpROM, JsrROM, and CmpRA macros. &RomFixIndex is a count of the total
|
||
; number of these references, and is also used to synthesize the label
|
||
; names for them. The reference labels have the form
|
||
; RXXX000, RXXX001, RXXX002, ...
|
||
; See the Macro definitions for JmpROM, JsrROM and CmpRA (near the top of
|
||
; this file) for more info.
|
||
;
|
||
; MkTbl is a macro only because assembler while loops will not work
|
||
; outside of macros.
|
||
;
|
||
MACRO
|
||
MkTbl
|
||
gbla &RomFixIndex
|
||
while &RomFixIndex <> 0 do
|
||
&RomFIxIndex seta &RomFixIndex - 1
|
||
dc.l RXXX&I2S(&ROMFIXINDEX,-3) - FixUpTbl
|
||
endwhile
|
||
dc.l 0 ; Zero entry marks end of table
|
||
ENDM
|
||
|
||
FixupTbl MkTbl
|
||
|
||
;########################### END PATCHES CUT BACK CODE ################################
|
||
|
||
EndProc
|
||
END
|