mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-11-26 01:49:19 +00:00
9813 lines
378 KiB
Plaintext
9813 lines
378 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
|