; ; File: PatchPortableROM.a ; ; Contains: patches for the first ROMs shipped in a Macintosh Portable ($037A) ; ; Copyright: © 1985-1992 by Apple Computer, Inc., all rights reserved. ; ; Change History (most recent first): ; ; <66> 1/19/92 DTY Look at emAppleTalkInactiveOnBoot before getting the AppleTalk ; version. If AppleTalk is inactive, donÕt set up the serial port ; for use by AppleTalk. This is part of a large conspiracy to ; convince the universe that AppleTalk really isnÕt around if it ; is inactive. ; <65> 12/26/91 RB Rename definition of SleepQRec in the serial patch because it is ; also used for Power Mgr. ; <64> 12/2/91 SAM Using official boxflag equates now. ; <63> 10/28/91 SAM/KSM Rolled in Regatta file: ; Added Asahi Sony icons. ; To distinguish between the Portable and Asahi (It's a Sony!) ; that have the same ROM number & boxFlag, if the ROM minor ; version is 1.1f1 then boxAsahi is jammed into BoxFlag. This is ; placed before Gestalt gets loaded and uses boxFlag. ; <62> 8/30/91 DTY Define onHcMac in this file because itÕs not an available ; feature in BBSStartup any more. ; <60> 6/12/91 LN added #include 'InternalOnlyEqu.a' ; <59> 6/12/91 LN removed #include 'HardwareEqu.a' ; <58> 3/18/91 gbm SAM, #gbm-0009: Take out code that saves and restores logical ; memory size and physical memory size around the installation of ; the RAM-based Gestalt (the portable ROM does it wrong, and we ; don't want its values) ; <57> 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. ; <56> 3/15/91 DTY kip, #fixGestalt: Add Gestalt fixes ('ptch' 5) to Portable ; because some of GestaltÕs globals are trashed. ; <55> 3/4/91 dba dty: get rid of SysVers conditionals ; <54> 2/26/91 eh (djw) Fixed bug that was causing crash on serial read if a break ; is received. An address offset was off by 2. ; <53> 2/21/91 eh (djw) Fixed bug in the serial driver that was preventing use of ; one port when Nike was printing on the other. ; <52> 1/19/91 mbs (jg) Include ATalkPrivateEQU.a to get AGBHandle equates since ; they were moved out of ATalkEQU.a. ; <51> 1/19/91 eh (djw) Patch Port A async serial driver headers to insert ; signature longword used by serial driver linked patch. Insert ; signature before already patched Port B headers. Changed port b ; arbitration code to call the new 'atkv' Gestall call instead of ; the old 'atlk'. ; <50> 1/14/91 eh (djw) Added external clocking support for Nike Printer to the ; Async Serial Driver. ; <49> 12/15/90 djw Add SCSI Mgr support for Quantum 7.9 ROM problem by adding a ; separate TIB interpreter and replacing blind write ; <48> 12/14/90 dnf (jsm) Nuke the dummy patch on ExtFSHook. ; <47> 12/14/90 DFH Removed MoveHHi and StackSpace patches. They were to ; workaround a SuperCard 1.0 bug, but SuperCard 1.5 has been ; available for some time. SuperCard 1.0 initialization code ; lowered ApplLimit directly instead of calling SetApplLimit. This ; left HiHeapMark up high, so StackSpace returned less than the ; true amount, and SuperCard put up an alert because it thinks the ; stack is getting full. SuperCard 1.5 calls SetApplLimit, so ; HiHeapMark is OK. ; <46> 11/14/90 JSM Move come-from patch on _TEAutoView to fix dialog manager ; bug to DialogManagerPatches.a. ; <45> 9/25/90 KIP Change Sound Mgr. to a linked patch. ; <44> 9/21/90 VL Moved PowerMgr patches to PowerMgrPatches.a so that SystemTask ; will not be patched before the Notification Manager gets to ; patch it. ; <43> 9/20/90 KST Install a dummy patch for ExtFSPatch so that it will work for a ; linkpatch. ; <42> 8/18/90 dba get rid of ptchInst 7 and 8 (Sony Format and Eject patches) as ; they are now linked patches ; <41> 8/14/90 DTY Removed TextEdit patches since theyÕre in a linked patch now. ; (For real this time.) ; <40> 8/14/90 JWK NEEDED FOR SIXPACK: Removed old Slot Mgr Gestalt selectors. ; <39> 8/13/90 JWK NEEDED FOR SIXPACK: Added NuBus and Serial Gestalt selectors. ; <38> 8/8/90 SAM Changing DispatchHelper & ProcHelper into an old style ptch. ; ¥¥¥--> Temporary <--¥¥¥ Remove when the Sound ptch get converted ; into an Lptch. ; <37> 7/30/90 dnf Remove installation of ptch 18 (File Manager) and ptch 6 (Btree ; Manager), now linked patches ; <36> 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 ; <35> 7/20/90 DTY Removed ptchInst 10 & 11 (Bass patches) since Bass is (finally) ; a linked patch. ; <34> 7/19/90 CCH NEEDED FOR SIXPACK: Removed HwPriv patch, its now a ; linked-patch. ; <33> 7/19/90 GMR Install ptch 7 to change eject track from 79 to 40. ; <32> 7/16/90 gbm Warning cleanup ; <31> 7/2/90 DTY Removed ptchInst 21 since Resource Manager extensions are now a ; linked patch. ; <30> 6/25/90 DTY Removed ptchInst 9 since ScrollSpeedFix is now a linked patch. ; <29> 6/19/90 VL Remove PtchInst 29 since MiscPatches is a linked patch ; now. ; <28> 6/12/90 JSM Remove PtchInst 33 since PPC Toolbox is a linked patch now. ; <27> 6/7/90 EMT Remove PtchInst 17 since Layer Manager is a linked patch now. ; <26> 6/7/90 VL Remove ptchinst 28 since HelpMgr is a linked patch now. ; <25> 5/29/90 DDG NEEDED FOR SIXPACK: Changed all the sixpack conditionals from ; six-point-oh-seven to six-point-oh-six. ; <24> 5/10/90 JSM AliasMgr now a linked patch, don't install it here anymore. ; <23> 5/4/90 HJR Reset the projector date on this file. ; <22> 5/3/90 MSH Fixed the modem and can't read 800k disks bug. ; <21> 5/1/90 CCH Added some Gestalt patches (nMgr, Misc, removed VIA,SCC,RBV). ; <20> 4/21/90 csd added patch install of ptch 16 (PrGlue). ; <19> 4/16/90 DDG Rolled over changes from the split off sources including a ; hwpriv patch and installing patch 25 (generic system patch). I ; also changed the spline fonts equate to use the build variable ; hasSplineFonts. ; <18> 4/4/90 KON Removed ptchinst 36 and 44 since they are now linked patches. ; <17> 3/29/90 KON Add ptch 40, quickdraw stuff for all B&W machines. ; <16> 3/27/90 PKE Deleted import (currently conditionalized out) of NewSwapIcon, ; which no longer exists in this PTCH. ; <15> 3/26/90 PKE Moved definition of symbols that control Script Mgr patch and ; 'ptch' installation into ScriptPriv.a. Renamed symbols and added ; some. ; <14> 3/23/90 NC Added ptch 43 for System 6.0.6 on up. This is for Sound. ; <13> 3/4/90 PKE Changed _UprText to _UpperText to match new Traps.a. ; <12> 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). ; <11> 2/22/90 PKE Replaced obsolete _LwrStringToUpr opword with _UprText. Removed ; setting of temporary sVectFixSpExtra vector (see <4>); we no ; longer need it. ; <10> 1/31/90 SMB NEEDED FOR Scripts604 and 6.0.5 - Fixed Dialog Mgr bug that ; didn't get rolled into rom. Have to do a come-from patch in ; TEAutoView to fix a rect for R-to-L text. ; <9> 1/29/90 MSH Misplaced label. All better now. ; <8> 1/29/90 MSH PowerOff fix is changed to remove the power control call to the ; PMGR. The call prevented the AppleTalk driver from resetting ; the SCC before closing. Added a wake up procedure for the sleep ; queue to reset the SCC whenever waking and no one is using the ; driver. GMR added a patch to the EDisk driver to return ; IOActCount correctly. ; <7> 1/18/90 MSH Roll in latest version of Pmgr trap from main sources. Fixed the ; trap to preserve the VIA sound enable bit. Added intercept to ; PowerOff trap to reset the SCC before calling the ROM version. ; <6> 1/12/90 CCH Added include of ÒHardwarePrivateEqu.aÓ. ; <5> 1/11/90 PKE Changed quotes in previous comment to ÒÓ so scripts don't get ; messed up. ; <4> 1/11/90 PKE Initialize Script Manager's new sVectFixSpExtra vector. Changed ; so PtchInst 0 is conditionalized on ÒScripts604 OR (SysVers >= ; $605)Ó instead of ÒScripts604 OR (SysVers >= $700)Ó; at the ; moment, this won't affect anything since Scripts604 is presently ; TRUE for the 6.0.5 build. ; <3> 1/4/90 BBM NEEDED FOR 6.0.5. We now patch out the soundmanger on all ; cpuÕs. ; <2> 1/4/90 dba converted header; used PatchMacros setTrap and stuffOldTrap ; instead of Set/GetTrapAddress (makes the object code a little ; bit shorter) ; <1> 12/17/89 CCH Adding for the first time into BBS. ; <6.1> 12/13/89 MSH NEEDED FOR 6.0.5:Two more fixes. 1) Added fix to PMGR ADB send ; command. Commands ; <6.0> 12/11/89 GMR Added ptchInst 8; Sony Format patch is now in it's own patch ; file (FormatPatch.a). ; <5.9> 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. ; <5.8> 12/4/89 MSH NEEDED FOR 6.0.5: Completely new patch for the PmgrOpPatch to ; fix two problems. 1) Moved the delay in SerialPower to fix poor ; hardware design, i.e. let the -5v generator to stabilize before ; turning on the other power planes. 2) Added modem port polling ; to PmgrOp to support high speed (57.6kb) serial. ; <5.7> 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. ; <5.6> 11/21/89 EMT NEEDED FOR 6.0.5: Added humane scrolling. ; <5.5> 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. ; <5.4> 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. Also (applies to 7.0 only) - fixed ; install for 4.7 to use lea instead of leaROM. ; <5.3> 10/15/89 BAL Added support for 32-Bit QuickDraw pictures via ptch 36 ; <5.2> 10/6/89 JSM Removed SnarfMan 'ptch', now PACK 13. ; <5.1> 9/26/89 CVC Added PPC Toolobox as a 'ptch'. ; <5.0> 9/25/89 EMT Added ptchs 18, 6, 29. ; <4.9> 9/19/89 RLC Added Balloon Help (ptch 28) to file. ; <4.8> 9/18/89 BBM Install resource manager extensions, ptch 21 ; <4.7> 9/18/89 PKE For 7.0, patch Script Manager internal routine SwapIcon to use ; new 'kscn' resource type instead of 'SICN'. ; <4.6> 9/17/89 PKE Decided to patch out GetScript/SetScript entirely in ptch 27, so ; we no longer patch them here (see 4.5). Also, for 7.0 we now ; install the Script Manager's Gestalt function in ptch 27 instead ; of here (see 2.7). ; <4.5> 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. ; <4.4> 9/4/89 PKE Install Script Manager 7.0 extensions, ptch 27. Set Script Mgr ; version for 7.0. ; <4.3> 8/28/89 PKE For 7.0, initialize additional Script Mgr vectors for ; SMgrCalcRect and SMgrInitFonts. ; <4.2> 8/27/89 PKE NEEDED FOR Scripts604, 6.0.5: Bump Script Manager version for ; Scripts604 or SysVers > $604, since IntlForce bug fix (3.8) is ; installed. ; <4.1> 8/25/89 SMB NEEDED FOR Scripts604: install TextEdit (ptch0) for 6.0.4 Script ; System builds. ; <4.0> 8/21/89 PKE NEEDED FOR 6.0.4: Conditionalize 3.8 for Scripts604 OR (SysVers ; > $604) ; <3.9> 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. ; <3.8> 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). ; <3.7> 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?). ; <3.6> 8/20/89 PKE NEEDED FOR 6.0.4: Added (from PatchIIciROM.a) MkTbl macro and ; code to fix up patch addresses. This is needed to make ; JmpROM/JsrROM/CmpRA work, and fixes a problem in the ; InitProcMenu patch (3.4). ; <3.5> 8/19/89 MSH Commented out GGD's Sane Optimization, it breaks Excel 2.2. ; <3.4> 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.3> 8/15/89 prp Added Alias Manager and Folder Manager support. ; <3.2> 8/11/89 MSH Expanded the Sleep trap patch to fix the passing of the sleepnow ; code to the sleep queue entries, sleepnow should be converted to ; sleepdemand before calling them. ; <3.1> 8/10/89 CCH NEEDED FOR 6.0.4: Added gestalt location error patch and ; installation. ; <3.0> 8/9/89 CCH NEEDED FOR 6.0.4: Added patch to gestaltQuickdrawVersion to ; return two digit versions. Added patch to make ; gestaltLowMemorySize and gestaltParityAttr exist on Portable. ; <2.9> 8/8/89 dba NEEDED FOR 6.0.4: added InitProcMenu patch ; <2.8> 8/7/89 PKE NEEDED FOR 6.0.4: In gestaltScriptMgr function, if gestalt ; selector is undefined, just leave gestalt result alone. ; <2.7> 8/5/89 PKE NEEDED FOR 6.0.4: Add Gestalt function for Script Manager, ; install corresponding Gestalt selectors. ; <2.6> 7/26/89 GGD NEEDED FOR 6.0.4 Added SANE optimization to bypass the package ; manager and dispatch directly to the SANE package in ROM. ; <2.5> 7/24/89 PKE NEEDED FOR 6.0.4: Remove Script Manager patches, since these ; were fixed in Esprit ROM after all. ; <2.4> 7/19/89 JSM Install SnarfMan 'ptch'. ; <2.3> 7/10/89 PKE NEEDED FOR 6.0.4: Put in Script Manager ROM patch code, but ; don't install patches yet (we need to wait for final ROM and ; adjust addresses accordingly). We patch InitResources, ; UprString, GetFormatOrder to match changes in Aurora ROM that ; were too late for Esprit. ; <2.2> 7/3/89 NJC Sound Manager Extensions (ptch 23) rolled in for real. ; <2.1> 6/19/89 MSH Low power resource ID numbers changed. ; <2.0> 5/31/89 CEL Only defined Spline_Font variable if it is undefined - makes it ; easier to build test 6.0.4 systems ; <1.9> 5/25/89 EMT Correctly detach all SICN and STR resources. ; <1.8> 5/25/89 EMT Added Window Manager extensions for Esprit. ; <1.7> 5/24/89 MSH Detach all SICN and STR resources. ; <1.6> 5/3/89 CEL Rolling in Bass for the first time into EASEÉ ; <1.5> 3/30/89 MSH Load both the system disk version and the rom version. ; <1.4> 3/30/89 MSH Added a load of the watch cursor from rom and saved the pointer ; in pmgr locals. ; <1.3> 3/30/89 MSH Removed the unmount patch completely, in rom now. ; <1.2> 3/22/89 MSH Cache control trap moved to ROM and Unmount patch made ; universal. Unmount install searches ROM for required entry ; points and pokes them into vectors for unmount patch to use. ; <1.1> 3/15/89 MSH Real patches added today. Unmount patch for AppleShare ("ptch ; 8"), is loaded if there. Cache trap is here now but will be ; rolled into ROM for next release. ; <1.0> 3/6/89 CCH Adding to EASE for first time. ; STRING ASIS if (&type('onHcMac') = 'UNDEFINED') then onHcMac: equ 1 endif if (&TYPE('has3rdFloppy') = 'UNDEFINED') then has3rdFloppy: equ 0 endif LOAD 'StandardEqu.d' INCLUDE 'PatchMacros.a' INCLUDE 'GestaltEqu.a' ; added <08/05/89 pke> INCLUDE 'GestaltPrivateEqu.a' ; <21> INCLUDE 'PackMacs.a' ; <3.7> <08/21/89 pke> INCLUDE 'ScriptPriv.a' ; <3.8> <08/21/89 pke> INCLUDE 'ApplDeskBus.a' ; <5.5> INCLUDE 'HardwarePrivateEqu.a' INCLUDE 'ATalkEqu.a' ; INCLUDE 'ATalkPrivateEQU.a' ; <1/19/91 mbs> INCLUDE 'EDiskEqu.a' ; <8> Include 'SCSIEqu.a' ; <49> djw Include 'SCSIPriv.a' ; <49> djw Include 'InternalOnlyEqu.a' Include 'SonyEqu.a' ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Misc Equates & Macros ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; UnimplementedTrap EQU $A89F ; unimplemented trap IF (&TYPE('SPLINE_FONT') = 'UNDEFINED') THEN SPLINE_FONT: EQU hasSplineFonts ENDIF IF (&TYPE('Scripts604') = 'UNDEFINED') THEN Scripts604: EQU 0 ENDIF ; The following symbols are defined in ScriptPriv.a. They control whether <15> ; 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 ; ;------------------------------------------------------------------------------- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; End Macros ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ROM37AFix PROC EXPORT IMPORT PatchInit EXPORT StartPatch,CutBack ; Cut back Code: ; ; SysBase is the entry point for ROM37AFix Upon entry D1.L contains our handle. StartPatch Bra PatchInit ; Go do initialization stuff. D1 contains handle to us. DC.B 'PTCH' ; resource type DC.W $37A ; patch ID $37A. 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 SysBase in D1 from SysPatch) CutBack _SetHandleSize ; adjust our size Moveq #$7F,D0 ; a soon to be large number Swap D0 _CompactMem ,SYS ; of course there must be a comma! Rts ; all done ENDPROC ; added <2.3 07/10/89 pke> ;######################################################################################### ;################################ PATCH CODE GOES HERE ################################### ;######################################################################################### ;----------------------------------------------------------------------------------------- ; ; 12/13/89 MSH ASendRequestPatch - Fixes a bug that has existed since initial design. ; There is a small window of time where a Send Request queue element is put in the queue ; for later transmission and an interrupt occurs. The interrupt uses the same data storage ; area and effectively wipes out the send. This patch masks interrupts during the posting ; of the element to provent it being overwritten. ; ;----------------------------------------------------------------------------------------- TCBE EQU 12 TSktNum EQU 4 TQElPtr EQU $10 NextTID EQU $2B0 TTimeout EQU $40 OurDCE EQU $2AC ; Find a free TCB and open a dynamic socket for the transaction. ATPPatch PROC EXPORT ASendRequest CMP.L #$92AA12,(SP) ; was this called from ROM? BNE.S @ATPPatchDone ; exit if not CMP.W #sendRequest,csCode(A0) ; is this a send request BNE.S @ATPPatchDone ; exit if not ADDQ #4,SP ; throw away return address MOVE.L AbusVars,A2 ; A1 -> MPP variables MOVE.L ATPVars(A2),A2 ; A2 -> our local variables AND.B #FlagMask,ATPFlags(A0) ; Leave only flag bits MOVE.W #TooManyReqs,D0 ; Assume error case MOVEQ #TCBE-1,D2 ; D2 = offset into TCB table @10 TST.B TSktNum(A2,D2) ; Is this entry free? DBEQ D2,@10 ; Find one BNE.S @ATPPatchexit ; Error if none found ; BSR SndRqInit ; Set A3 -> data area JSR $92AE6A BNE.S @ATPPatchexit ; Error CLR.B D1 ; LEA ATPRead,A1 ; A1 -> socket listener MOVE.L #$92B2F4,A1 MOVE.L A1,Listener(A3) ; Set in q element MOVE.W #OpenSkt,D0 ; D0 = code for open socket ; BSR CallMPP ; Do the open socket JSR $92AEE6 BEQ.S @15 ; Branch on no error ; BSR FreeDataArea ; Free up MPP data area JSR $92B600 ; BRA.S @AtpExit @ATPPatchExit MOVE.L OurDCE(A2),A1 MOVE.L JIODone,A0 JMP (A0) ; Go to IODone vector @ATPPatchDone RTS ; Set info in the TCB and write out the request @15 MOVE.B Socket(A3),D1 ; D1 = socket number from DDP ; BSR SndRqCommon ; Set up JSR $92AE7C MOVE.L A0,TQElPtr(A2,D2) ; Set it to our q element LEA NextTID(A2),A1 ; A1 -> NextTID MOVE.W (A1),ReqTID(A0) ; Set in q element for caller BSET #TIDValid,ATPFlags(A0) ; TID now valid ADDQ #1,(A1) ; Next LSR #2,D2 ; Next offset MOVE.B D1,TSktNum(A2,D2) ; Set socket num LEA TTimeout(A2,D2),A1 ; A1 -> place for timeout CLR.B (A1) ; Hold off timer now MOVE.L A1,-(SP) ; Save A1 BSR SendRDequeue ; Dequeue call MOVE.L (SP)+,A1 ; Restore A1 ; BSR ReTransSetup ; Setup for transmission JSR $92AF20 ; BSR DoWrite ; Write out the request JSR $92AE9C ; BSR FreeDataArea ; Free up data area JSR $92B600 MOVE.B TimeoutVal(A0),(A1) ; Start timer MOVEQ #0,D0 RTS SendRDequeue MOVE SR,-(SP) ; Hold off interrupts MOVE #SCCLockOut,SR ; BRA Dequeue ; Dequeue the request and return JMP $92ABA2 ENDP ; ;____________________________________________________________________________ <21> ; Patches to Gestalt Functions ;____________________________________________________________________________ ; The _Gestalt trap is patched to ensure that new gestalt functions ; reside in the System Heap. ; ; The following gestalt selectors are patched or added in this file: ; - gestaltLowMemorySize ; - gestaltParityAttr ; - gestaltMiscAttr ; - gesaltNotificationMgrAttr ; - gestaltQuickdrawVersion ; - gestaltNuBusConnectors <39> ; - gestaltSerialAttr <39> ; ; The following gestalt selectors are removed in this file: ; - gestaltRBVAddr ; - gestaltSCCReadAddr ; - gestaltSCCWriteAddr ; - gestaltVIA1Addr ; - gestaltVIA2Addr ; - gestaltSlotAttr <40> ; - gestaltSlotCount <40> ; - gestaltFirstSlot <40> ; ;----------------------------------------------------------------------------------------- ; ; <3.1> 8/10/89 CCH GestaltPatch - This patch ensures that new gestalt functions are in ; the system heap or in ROM. It does this by intercepting the OS trap $AD and ; performing a check on the gestalt function address passed in. It does not perform ; this check on standard _Gestalt traps, only on _NewGestalt and _ReplaceGestalt traps. ; ;----------------------------------------------------------------------------------------- gestaltTrapID EQU $A1AD ; trap ID of _Gestalt function GestaltPatch PROC EXPORT EXPORT gestaltAddr cmp.w #GestaltTrapID,d1 ; are they adding a function? beq.s @goROM ; if not, then skip patch move.l SysZone,a1 ; get ptr to system zone header cmpa.l (a1),a0 ; is gestalt function below system heap? bls.s @goROM ; if so, then no error cmpa.l RomBase,a0 ; is gestalt function in ROM? bcc.s @goROM ; if so, then no error move.l #gestaltLocationErr,d0 ; otherwise, return a location error rts @goROM move.l gestaltAddr,a1 ; get original trap address jmp (a1) ; jump into Gestalt trap in ROM gestaltAddr dc.l 0 ; space to store original trap addr ENDP ;----------------------------------------------------------------------------------------- ; ; 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 <21> gestaltMisc PROC EXPORT with gestaltParmFrame link a6,#localFrame clr.l d3 ; clear result @hasBootGlobs bclr #gestaltBootGlobals,d3 ; we don't have boot globals <21> @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 ;----------------------------------------------------------------------------------------- ; ; <3.0> 8/10/89 CCH GestaltLowMem - This is the gestaltLowMemorySize selector, which ; was created after the Esprit ROM froze. ; ; Routine gestaltLowMem ( gestaltSelector: OSType; VAR gestaltResult: Longint) : OSErr; ; ;----------------------------------------------------------------------------------------- GestaltLowMem PROC EXPORT with gestaltParmFrame link a6,#localFrame move.l gestaltResult(a6),a0 ; get address to place result move.l SysZone,(a0) ; system zone starts at top of low-mem 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 ;----------------------------------------------------------------------------------------- <40> ; ; <39> 8/13/90 JWK GestaltSerial - This is the gestaltSerialAttr selector. ; The Portable has GPI connected on both ports. GestaltSerial PROC EXPORT ; Portable has no serial attributes with gestaltParmFrame link a6,#localFrame move.l gestaltResult(a6),a0 ; get address to place result move.l #(1< ; ; <39> 8/13/90 JWK GestaltNBCon - This is the gestaltNuBusConnectors selector. ; GestaltSerial - This is the gestaltSerialAttr selector. ; Since the Portable should return zero, we share the GestaltParity function's code ; to return a zero. ; GestaltNBCon PROC EXPORT ; Portable has no NuBus ;----------------------------------------------------------------------------------------- ; ; <3.0> 8/10/89 CCH GestaltParity - This is the gestaltParityAttr selector, which was ; created after the Esprit ROM froze. ; ; Routine gestaltParity ( gestaltSelector: OSType; VAR gestaltResult: Longint) : OSErr; ; ;----------------------------------------------------------------------------------------- GestaltParity PROC EXPORT with gestaltParmFrame link a6,#localFrame move.l gestaltResult(a6),a0 ; get address to place result move.l #0,(a0) ; Portable will never have parity 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 ;----------------------------------------------------------------------------------------- ; ; <3.0> 8/10/89 CCH GestaltQDVers - This is the gestaltQDVersion selector, which was ; created after the Esprit ROM froze. ; ; Routine GestaltQDVers ( gestaltSelector: OSType; VAR gestaltResult: Longint) : OSErr; ; ;----------------------------------------------------------------------------------------- GestaltQDVers PROC EXPORT with gestaltParmFrame link a6,#localFrame move.l gestaltResult(a6),a0 ; get address to place result move.l #gestaltOriginalQD,(a0) ; Portable has original QD 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 ; <4.6><15> ;******************************************************************************** ;******** start of Gestalt function for Script Mgr <2.7> <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 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 ;********** end of Gestalt function for Script Mgr <2.7> <08/05/89 pke> ********** ENDIF ; <4.6> ;----------------------------------------------------------------------------------------- ; 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 $11446 ; place to rejoin ROM in InitMenus ; the following code is copied out of the Menu Manager InitProcMenu 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 <3.4> move.l MenuList,a0 ; get the menu list <3.4> move.l (a0),a0 ; dereference the menu list <3.4> move.w d1,mbResID(a0) ; store MBDF ID <3.4> rts ; return to InitProcMenu caller <3.4> endproc ;____________________________________________________________________________ ; Script Manager patch to Pack6, fixes problem with pointer to unlocked ; handle in Transliterate. <3.7><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. <3.8><08/21/89 pke> ; Only do the second fix for Scripts604 OR (SysVers > $604) <4.0><08/21/89 pke> ; IF doScriptMgrPack6Fix AND (NOT installScriptMgrPtch39) THEN ; <12><15> ptchPack6 PROC Export fromROMLwrString EQU $0797A fromROMCharType EQU $1745C fromROMFindWord EQU $176B6 fromROMTranslit EQU $1760A toROMTranslit EQU $17610 ROMPack6 EQU $1E3F4 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 ; <12> ;============================================================================ pke <3.9> ; 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 $079D4 ROMRelStringAfterEntString equ $079FE ROMEntStringAfterLEAUpperTab equ $07A5E ;______________________________________________________________________ ; ; 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 <3.9> 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 ; <3.9> ;______________________________________________________________________ ; ; 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 ; <3.9> ; ; 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 ;_________________________________________________________________________________________________________ ; ; <3.9> <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 <3.9> 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 ; <5.4><12><15> ;============================================================================ pke <5.4> ; Patch Script Manager routines InitDateCache and String2Date for bug fixes ; needed by HyperCard. ; ---------------------------------------------------------------------------- proc export NewInitDateCache,NewString2Date ROMValidLong equ $1895A ; <5.4> ROMBlock2String equ $18996 ; <5.4> ROMMatchString equ $18A02 ; <5.4> ; in InitDateCache ($18A60): ROMAfter2ndJSRCopyArray equ $18BC8 ; <5.4> ROMExit equ $18C40 ; <5.4> ; in/after String2Date (18C6E): ROMAfterDBNE equ $18DB4 ; <5.4> ROMDTComExit equ $18F04 ; <5.4> ROMFixValue equ $18F4C ; <5.4> ROMDateTimeEntry equ $18F5C ; <5.4> 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 ; <5.4> theMonths DS.B MonthList ; <5.4> 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 <5.4>. ; ---------------------------------------------------------------------------- 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 <5.4> ; 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 <5.4> ; 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 <5.4> ; 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 ; <5.4> Exit JmpROM ROMExit ; <5.4> ; 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 <5.4> MOVE.L d4,A1 ; into local frame moveq #0,d0 ; Block2String wants a long! <5.4> 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 <5.4> ADD.L #Str15,d4 ; get next string to transfer ADD.w #Str15,A4 ; into next string in local frame <5.4> 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: É <5.4> ; ---------------------------------------------------------------------------- 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 <5.4> ; for final string (remove .s) ; ValidLong(position,textLength): longint MOVE.L stringPosition(A3),A0 JsrROM ROMValidLong ; get number in text at TokenRec.position <5.4> BMI DTComExit JsrROM ROMFixValue ; <5.4> bra @TokenRecognized ; get next token (remove .s) <5.4> @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 <11><13> TST.W D4 BPL.S @SearchForDay ; <5.4> ; 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) ; <5.4> MOVE.W #DayMonthLen,-(SP) MOVE.W #NumMonths+NumDays,-(SP) ; check for both at once JsrROM ROMMatchString ; <5.4> 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 <5.4> @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 ; <5.4> 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 <5.4> @HaveDay ; <5.4> ST DayFound(A6) ; record that day was found <5.4> 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 ; <5.5><12><15> ;============================================================================ pke <5.5> ; 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 $17B0A ROMAfterClrDeadKey equ $17B1A ROM@1dbra equ $17B26 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! <5.5> JmpROM ROMAfterClrDeadKey ; <5.5> @1 JmpROM ROM@1dbra ; <5.5> endwith endproc ENDIF ;----------------------------------------------------------------------------------------- IF doScriptMgrLwrString2 AND (NOT installScriptMgrPtch27) THEN ; <5.9><15> ;============================================================================ pke <5.9> ; 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 ;----------------------------------------------------------------------------------------- ; ; 1/27/90 GMR EDiskPatch - Fixes EDisk drivers Prime routine by patching HWDepProcs ; which get called by prime after the move is complete. The new HWDepProcs ; first check to see if called by Prime, and if so, stuff the byte count (in d4) ; on the stacks 'scratch longword', which will later be pulled off and stored ; in ioActCnt and added to dCtlPos at the end of Prime. We patch each of ; the HWDepProcs (even SLIM's, though they presently are not used). ;----------------------------------------------------------------------------------------- EDiskPatch PROC EXPORT HWDepRAM,HWDepROM,HWDepSLIM,vRAMExit,vROMExit,vSLIMExit HWDepRAM move.l d0,-(sp) ; save d0 move.l 4(sp),d0 ; get return address and.l Lo3Bytes,d0 ; only check 24 bit part of address cmpi.l #$00929F54,d0 ; were we called by Prime? (just before the bug)? bne.s @exit ; no, get out of here move.l d4,8(sp) ; yes, fix bug by stuffing the byte count on stack @exit move.l (sp)+,d0 ; restore d0 vRAMExit jmp $00900000 ; and jump back to orig HWDep proc HWDepROM move.l d0,-(sp) ; save d0 move.l 4(sp),d0 ; get return address and.l Lo3Bytes,d0 ; only check 24 bit part of address cmpi.l #$00929F54,d0 ; were we called by Prime? (just before the bug)? bne.s @exit ; no, get out of here move.l d4,8(sp) ; yes, fix bug by stuffing the byte count on stack @exit move.l (sp)+,d0 ; restore d0 vROMExit jmp $00900000 ; and jump back to orig HWDep proc HWDepSLIM move.l d0,-(sp) ; save d0 move.l 4(sp),d0 ; get return address and.l Lo3Bytes,d0 ; only check 24 bit part of address cmpi.l #$00929F54,d0 ; were we called by Prime? (just before the bug)? bne.s @exit ; no, get out of here move.l d4,8(sp) ; yes, fix bug by stuffing the byte count on stack @exit move.l (sp)+,d0 ; restore d0 vSLIMExit jmp $00900000 ; and jump back to orig HWDep proc ENDPROC ; ---------------------------------------------------------------------------- ;_________________________________________________________________________________________ <50><51> EVA ; Async Serial Driver Patch ; ; Traps patched: -- The AsyncVector, which is in the middle of the OS ToolTable ; is patched, Trap number = $A0BE ; ; HISTORY: ; <50> New patch: ; 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. ; -- Patched bypass mode driver to set bit 3 of AsyncErr if break rcvd. ; added BAP support: ; -- patched out .Bin and .Bout driver headers to get driver storage pointer ; from expanded mem. ; -- patched out B port interrupt handlers to get driver storage pointer ; from expanded mem and to get DCE pointer from Unit Table. ; ; <51> We patch all the port A driver headers (port B driver headers 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'. ; Also, fix the port arbitration code in Open and Close to make call to the ; new 'atkv' Gestalt call instead of the old 'atlk' call. We do this because ; the new call return atalk version number regardless of whether MPP driver ; is open (i.e. appletalk is active). ; ; <53> 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. ; <54> Fix address offset for the readrqdone routine. we were off by 2. ; We were crashing if read pending and break rcv'd. ; <57> Status calls 9 and $8000 return static version number instead ; of what's in the DCE. ;_______________________________________________________________________ AsyncPatch proc export SerialPatch ; ; equates ; PortAVars EQU SerialVars ; serial chan A variables and buffer SerialVers equ 5 ; current version number 3/91 <57> ; ; 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 serBufSize 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> SleepQRec1 EQU 140 ;(12)sleep queue record for chrysalis <65> rb LclVarSize EQU 152 ; output driver storage size ;____________________________________________________________________ ; ; ROM address offsets ; ;____________________________________________________________________ ; come from patch equates fromAOutOpen EQU $30d84 fromAInOpen EQU $30d18 fromBOutOpen EQU $30db8 fromBInOpen EQU $30d20 fromControl EQU $31122 fromClose EQU $31036 fromStatus EQU $310d0 fromInitSCC EQU $30f2e ; open call patch equates backToAOutOpen EQU $30da4 ; returning to finish up Open routines in ROM backToAInOpen EQU $30d18 backToBOutOpen EQU $30dd6 backToBInOpen EQU $30d24 ROM_PollDtain EQU $31470 ; rom routines addresses we must push on the stack ROM_SCAIntHnd EQU $3155c ROM_RAIntHnd EQU $314ac ROM_TAIntHnd EQU $3137c ROM_SleepA EQU $30f74 ROM_SleepB EQU $30f7a ToContOut1 EQU $313a2 ; return to finish up interrupt routines in ROM ToRdReqDone EQU $315aa ;<54> ToCtlSet EQU $31254 ; Control patch equates for bypass driver backToControl EQU $31134 ; for fixing control calls ROM_CtlGood EQU $3116a ROM_CtlExit EQU $3116c ; Control Call 16 patch equates InitSCC EQU $30f1e ; Status patch equates for bypass driver backToStatus EQU $310ea ; InitSCC patch equates for bypass driver backToInitSCC EQU $30f2e initData EQU $30eea ; close patch equates SyncOutput EQU $31096 InitSCC1 EQU $30f24 ResetData EQU $30ffa ResetLth EQU $10 freePort EQU $3107c ; bypass driver ROM entrypoint addresses <51> ;port A ROM_AInEntryOpen EQU $30d16 ROM_AInEntryClose EQU $31092 ROM_AInEntryPrime EQU $313ae ROM_AOutEntryOpen EQU $30d82 ROM_AOutEntryClose EQU $3100a ROM_AOutEntryPrime EQU $312f4 ROM_AEntryControl EQU $3110e ROM_AEntryStatus EQU $310bc ;port B backToBInOpenStart EQU $30d1e backToBOutOpenStart EQU $30db4 ToBOutClose EQU $3101e backToBInPrime EQU $313b8 backToBOutPrime EQU $312fe backToBControl EQU $31118 backToBStatus EQU $310c6 ; for BAP only interrupt handler patches backToSCIntHnd EQU $31568 backToRXIntHnd EQU $314b8 backToTXIntHnd EQU $31380 ; for BAP only patches-- since these are not in Interfaces or Internals, ; where they should be LUsePortB EQU 17 ; request use of printer port ;<2.0> LFreePortB EQU 18 ; grant use of printer port ;<2.0> LStatPortB EQU 19 ; obtain current printer port status ;<2.0> LAPMgrPtr EQU $B18 ; This points to start of LapMgr ;<2.0> LAPMgrCall EQU 2 ; Offset to make LAP manager calls ;<2.0> ; ; Miscellaneous patch equates ; BInDCEOffset EQU 28 ; offset of .BIn DCE handle from UTableBase ;_______________________________________ ; ; Bypass Patch Code Entry Point ; (Patched Bypass mode routines here) ; ; SerialPatch move.l d0,-(SP) ; save reg d0 move.l 8(SP),D0 ; get D0 = return address _StripAddress ; strip nasty high bits cmpRA fromAInOpen,D0 ; test for ChkAConfig call from AInOpen beq.w OpenAFix cmpRA fromAOutOpen,D0 ; test for ChkAConfig call from AOutOpen beq.w OpenAFix cmpRA fromBOutOpen,D0 ; test for ChkBConfig call from BOutOpen beq.w OpenBFix cmpRA fromBInOpen,D0 ; test for ChkBConfig call from BInOpen beq.w OpenBFix move.l 4(sp),d0 ; one less level indirection for non-open calls _StripAddress ; strip nasty high bits 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 initSCC routine beq.w CloseFix cmpRA fromInitSCC,d0 ; to fix initSCC routine beq.w InitSCCFix move.l (sp)+,d0 ; restore regs RTS ; back to ROM ;_______________________________________________________________________ ; ; Close fixes ; -- do that nutty BAP stuff to free port B ; CloseFix ADD.L #8,SP ; pop save reg d0 and rtrn addr--we jump back move.l a1,-(sp) ; save DCE ptr ; for BAP ; if close is for port B,we'll just stomp over what ROM put in a6 cmpa.l #PortAVars,a6 ; from port A beq.s @common ; yes, then move on to common code move.l ExpandMem,a6 ; no, then get storage ptr for port B lea ExpandMemRec.emSerdVars(a6),a6 @common MOVE.L (A6),A2 ; get locals pointer <14Oct85> TST.B CtlOptions(A2) ; leave DTR unchanged? <14Oct85> bmi.s @1 ; bclr #7,XmitBits(A2) ; no, clear the DTR bit bclr #7,WR5AVal(A2) ; @1 bclr #3,XmitBits(A2) ; always clear Tx enable jsrROM SyncOutput ; delay until last char has cleared <14Oct85> ; output buffer LeaROM ResetData,A3 MOVEQ #ResetLth,D1 jsrROM InitSCC1 ; shut down the channel ; for BAP ; we replace ROM's port arbitration stuff with BAP stuff ; too bad the ROM port arbitration code comes at the END of the close call LEA SaveExInt(A2),A3 ; reinstall former int handlers <14Oct85> MOVE.L (A3)+,(A5) ; <14Oct85> MOVE.L (A3)+,(A4)+ ; <14Oct85> ADDQ.L #4,A4 ; <14Oct85> MOVE.L (A3)+,(A4)+ ; <14Oct85> MOVE.L (A3),(A4) ; <14Oct85> LEA SleepQRec1(A2),A0 ; A0 = ptr to sleep queue entry <65> rb _SlpQRemove ; Remove slpq proc move.l (sp)+,a1 ; restore DCE ptr MOVE.L DCtlStorage(A1),A0 ; get storage handle _DisposHandle ; get rid of it CLR.L DCtlStorage(A1) ; without a trace CLR.L (A6) ; get rid of ptr address <14Oct85> tst.w d3 ; what port are we? beq.s @freeB ; port b; do that BAP thing to free port jmpROM freePort ; port a; finish up in ROM @freeB move.l ExpandMem,a0 ; <66> tst.w ExpandMemRec.emAppleTalkInactiveOnBoot(a0) ; <66> If AppleTalk is inactive, donÕt set up the LAP manager bnz.s @freeThePort ; <66> AppleTalk is not active. move.l #'atkv',d0 ; what version of Appletalk? <51> _Gestalt tst.w d0 ; <66> Did Gestalt return an error? bne.s @freeThePort ; <66> Yes, so AppleTalk is not active. move.l a0,d0 ; get high byte (version) into low byte rol.l #8,d0 cmp.b #53,d0 ; is Atalk version 53 or greater? bge.s @useLAP ; yes, then call LAP manager, it exists @freeThePort jmpROM freePort ; no, then finish up in ROM @useLAP move.w #LFreePortB,d0 ; call LAP Manager to free port B move.b #useAsync,d1 move.l LAPMgrPtr,a0 jsr LAPMgrCall(a0) MOVE.W D3,D0 ; port selector OR.B #(1< move.w #0,d0 ; no error on close rts ;_______________________________________________________________________ ; ; 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 <53> extClkSrc equ %00101000 ; SCC clk src is TRxC (CTS) pin (WR11) <53> intClkSrc equ %01010000 ; SCC clk src is baud rate generator (WR11) <53> BRGEnbl equ %00000001 ; enable baud rate generator (WR14) <53> BRGDsbl equ %00000000 ; disable baud rate generator (WR14) <53> 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 ADD.L #8,SP ; pop save reg d0 and saved rtrn addr--we jump back move.l a3,d0 _StripAddress 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 <53> ; default to internally clocked state <53> bset.b #clkDvdBit,StopBits(a2) ; default to a divide-by-16 clock <53> moveq #intClkSrc,d0 ; internal clocking source <53> moveq #BRGEnbl,d1 ; enable baud rate generator <53> 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 <53> moveq #extClkSrc,d0 ; external clock source <53> moveq #BRGDsbl,d1 ; disable baud rate generator <53> clr.b HWHS(a2) ; make sure we're not trying to do HWHS <53> @load lea ClkMode,a0 ; load params into InitSCC data table <53> move.b d0,(a0) ; <53> lea BRGEnable,a0 ; <53> move.b d1,(a0) ; <53> movem.l (sp)+,d1/a0 ; restore reg's <53> @done jmpROM backToInitSCC ; finish up in ROM ;_______________________________________________________________________ ; ; Routine: Status ; Patch: We patch status to add a call to return the driver's version. StatusFix ADD.L #8,SP ; pop save reg d0 and rtrn addr--we jump back MOVE.W IOTrap(A0),-(SP) ; save trap to distinguish immed calls<14Oct85> MOVE.L A1,-(SP) ; save passed DCE for in/out <14Oct85> MOVE.W SR,-(SP) ; disable interrupts for ctl call <14Oct85> ORI #HiIntMask,SR ; LEA CSCode(A0),A0 ; get pointer to return parameters MOVEQ #StatusErr,D0 ; assume status error MOVE.L A2,D1 ; have our variables been set up? <14Oct85> Bgt @stat1 ; exit if not (only input side open)<14Oct85> 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 <57> jmpROM ROM_CtlGood ;_______________________________________________________________________ ; ; Routine: Control ; Patch: We patch control for the following reasons: ; 1) to add external clock support in control call 16 ; ControlFix ADD.L #8,SP ; pop save reg d0 and rtrn addr--we jump back MOVE.W IOTrap(A0),-(SP) ; save trap to distinguish immed calls<14Oct85> MOVE.L A1,-(SP) ; save passed DCE for in/out <14Oct85> MOVE.W SR,-(SP) ; disable interrupts for ctl call <14Oct85> ORI #HiIntMask,SR ; moveq #0,d0 ; for the killIO call LEA CSCode(A0),A0 ; get parameters MOVE.W (A0)+,D1 ; get opcode cmpi #16,d1 ; opcode 16? (ctlOptions) beq CtlSwitchCTSClock ; jmpROM backToControl ; if not, let ROM handle it ; 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] ; (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 <53> jsrROM InitSCC ; set up the SCC according to new value <53> jmpROM ROM_CtlGood ; finish up in ROM <53> ;_______________________________________________________________________ ; ; 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 OpenAFix add.l #4,sp ; saved d0 not needed MOVE.L (SP)+,A0 ; pop A0 = addr to continue ChkConfig move.l (sp)+,a2 ; save async open ret addr jsr (a0) ; finish ChkConfig (A1,D1,D2 params) move.l a2,d0 ; get Open return addr _StripAddress cmpRA fromAOutOpen,d0 ; test for ChkAConfig call from AOutOpen beq.s @out @in lea AsyncAIn,a2 ; store new driver header for AIn into DCE move.l a2,(a1) JmpRom backToAInOpen ; jump back into ROM in AInOpen @out lea AsyncAOut,a2 ; store new driver header for AOut into DCE move.l a2,(a1) LEA PortAVars,A2 ; local variables address PEAROM ROM_SleepA ; sleep proc for sleep queue entry peaROM ROM_PollDtaIn,-(sp) ; ROM--this proc handles disk poll data <20Oct85> peaROM ROM_SCAIntHnd,-(sp) ; ROM--Special RxD int handler <20Oct85> peaROM ROM_RAIntHnd,-(sp) ; ROM--RxD int handler <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 ; Channel B - almost the same patch as channel A ; Except of course for the BAP stuff OpenBFix move.l ExpandMem,a0 ; <66> tst.w ExpandMemRec.emAppleTalkInactiveOnBoot(a0) ; <66> If AppleTalk is inactive, donÕt set up the LAP manager bnz.s @appleTalkInactive ; <66> AppleTalk is not active. move.l #'atkv',d0 ; what version of Appletalk? <51> _Gestalt tst.w d0 ; <66> Check for an error from Gestalt bne.s @appleTalkInactive ; <66> AppleTalk is not active. move.l a0,d0 ; get high byte (version) into low byte rol.l #8,d0 cmp.b #53,d0 ; is Atalk version 53 or greater? bge.s @useLAP ; yes, than call LAP manager, it exists @appleTalkInactive ; no, use old chkConfig add.l #4,sp ; pop saved d0 -- not needed movea.l (sp)+,a0 ; pop A0 = addr to continue non-BAP ChkConfig move.l (sp)+,a2 ; save Open return addr jsr (a0) bra.s @gotPort @useLAP add.l #8,sp ; pop d0,ROM ChkConfig addr move.l (sp)+,a2 ; save Open return addr movem.l d1/a1-a2,-(sp) ; save out reg's we might use move.w #LStatPortB,d0 ; request status of the printer port move.l LAPMgrPtr,a0 jsr LAPMgrCall(a0) cmp.b #useAsync,d1 ; do we already own the port? beq.s @rstrReg ; yes move.w #LUsePortB,d0 ; no, request use of the printer port- move.b #useAsync,d1 ; for the serial driver- move.l LAPMgrPtr,a0 ; by calling the LAP Manager jsr LAPMgrCall(a0) cmp.w #noErr,d0 ; did we get the printer port? beq.s @rstrReg ; yes movem.l (sp)+,d1/a1-a2 ; restore reg's rts ; no,return to IO Core: we already popped ret addrs and regs @rstrReg movem.l (sp)+,d1/a1-a2 ; restore reg's @pwrPort MOVE.W D1,D0 ; Send port to power _SerialPower ; check for powering things up @gotPort move.l a2,d0 ; get Open return addr _StripAddress cmpRA fromBOutOpen,d0 ; test for ChkBConfig call from BOutOpen beq.s @out ; from .Bin lea AsyncBIn,a2 ; store new driver header for BIn into DCE move.l a2,(a1) JmpRom backToBInOpen ; jump back into ROM in BInOpen @out ; from .Bout lea AsyncBOut,a2 move.l a2,(a1) ; store new driver header for BOut into DCE move.l ExpandMem,a2 ; get storage ptr lea ExpandMemRec.emSerdVars(a2),a2 PEAROM ROM_SleepB ; sleep proc for sleep queue entry CLR.L -(SP) ; no disk poll routine PEA NewSCBIntHnd ; new special RxD int handler PEA NewRBIntHnd ; new RxD int handler pea NewTBIntHnd ; TxD int handler pea Lvl2DT ; SCC interrupt dispatch table, chan A pea NewExtBIntHnd ; External int handler JmpRom backToBOutOpen ; JUMP BACK INTO ROM ;________________________________________________________________________ ; ; Routine: RXIntHnd ; ; Arguments: A0 (input) -- chan A/B control read address ; A1 (input) -- chan A/B control write address ; ; Patch: forBAP, get driver storage ptr from expanded mem ; get DCE ptr from UTable NewRBIntHnd move.l ExpandMem,a2 ; use ExpandMem instead of PortBVars move.l ExpandMemRec.emSerdVars(a2),a2 movea.l UTableBase,a3 ; get .Bin DCE ptr in a3 movea.l BInDCEOffset(a3),a3 movea.l (a3),a3 MOVE.B SCCData(A0),D0 ; get the data byte jmpROM backToRXIntHnd ; and branch around 'redundant' 6.X code ;________________________________________________________________________ ; ; Routine: SCIntHnd ; ; Arguments: A0 (input) -- channel A/B control read address ; A1 (input) -- channel A/B control write address ; ; Patch: forBAP, get driver storage ptr from expanded mem ; get DCE ptr from UTable NewSCBIntHnd move.l ExpandMem,a3 ; use ExpandMem instead of PortBVars move.l ExpandMemRec.emSerdVars(a3),a2 movea.l UTableBase,a3 ; get .Bin DCE ptr in a3 movea.l BInDCEOffset(a3),a3 movea.l (a3),a3 move.b #1,(a1) jmpROM backToSCIntHnd ; back to ROM ;________________________________________________________________________ ; ; Routine: TBIntHnd ; ; Patch: forBAP, get driver storage ptr from expanded mem ; get DCE ptr from UTable NewTBIntHnd move.l ExpandMem,a2 ; use ExpandMem instead of PortBVars move.l ExpandMemRec.emSerdVars(a2),a2 JmpRom backToTXIntHnd ; back to ROM ;________________________________________________________________________ ; ; Routine: ExtIntHnd ; ; Patch: forBAP, get driver storage ptr from expanded mem ; get DCE ptr from UTable ; -- patch to set bit 3 in AsyncErr (had to patch in ALL code before). ; -- also fix the RdReqDone problem NewExtBIntHnd move.l ExpandMem,a3 ; use ExpandMem instead of PortBVars move.l ExpandMemRec.emSerdVars(a3),a2 movea.l UTableBase,a3 ; get .BIn DCE ptr in a3 movea.l 28(a3),a3 movea.l (a3),a3 bra.s ExtIntHnd NewExtAIntHnd LEA PortAVars,A3 ; get appropriate variables - chan A MOVE.L (A3)+,A2 ; get pointer to local variables MOVE.L (A3),A3 ; get .AIn DCE ptr in a3 ExtIntHnd MOVE.B D1,D2 ; changed bits AND.B postOptions(A2),D2 ; post this change? BEQ.S @0 ; br if not MOVEM.L D0/A0,-(SP) ; preserve these registers MOVE.W #IODrvrEvt,A0 ASL.W #8,D0 ; make room for 'changed' values MOVE.B D1,D0 SWAP D0 ; make room for driver refnum MOVE.W DCtlRefnum(A3),D0 _PostEvent ; and post the event MOVEM.L (SP)+,D0/A0 @0 TST.B D1 ; see if it's a change in break status BMI.S extBreak ; branch if it was a break interrupt LSL.B #2,D0 ; must be CTS change SMI CTSFlag(A2) ; set flags according to CTS ; This piece of code is used to detect a clock into the HWHS line ; and shut off the ext/sts interrupt for the handshake line. CMP.W #80,HSCount(A2) ; exceeded 80 transitions in 16 MS? <14Oct85> BCS.S @2 ; br if not <14Oct85> MOVEQ #-128,D0 ; ($80) leave break ints enabled <14Oct85> MOVEQ #15,D1 ; write register 15 <14Oct85> jsrROM ToCtlSet ; @2 MOVE.L Ticks,D2 ; get current tick time <14Oct85> CMP.L LastTime(A2),D2 ; same as last? <14Oct85> BEQ.S @3 ; br if so <14Oct85> MOVE.L D2,LastTime(A2) ; new last time <14Oct85> CLR.W HSCount(A2) ; restart count for new time <14Oct85> @3 ADDQ #1,HSCount(A2) ; update count <14Oct85> jmpROM toContOut1 ; BRA ContOut1--if freshly asserted, continue output<14Oct85> extBreak TST.B D0 ; check break level BMI.S @1 ; if it's asserted, terminate any input MOVE.B SCCData(A0),D0 ; otherwise (end of break), discard null @0 RTS ; and return @1 MOVEQ #BreakRecd,D0 ; note the break bset.b #3,AsyncErr(a2) ; we now note break level in status TST.B ReadCmd(A2) ; read request pending? beq.s @0 ; just return if done <7.1> jmpROM ToRdReqDone ; return to ROM code ;_______________________________________________________________________ <51> ; ; 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' ;_______________________________________________________________________ <51> ; ; jumping to ROM from our patched entry points ; AInOpen jmpROM ROM_AInEntryOpen ;port a 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 backToBInOpenStart ;port BOutOpen JmpRom backToBOutOpenStart BInClose moveq #0,d0 ; shorter to return than to jump to ROM rts BOutClose JmpRom ToBOutClose ; don't need to screw with this other than ; patch above BInPrime move.l ExpandMem,a2 ; use ExpandMem instead of PortBVars move.l ExpandMemRec.emSerdVars(a2),a2 ; JmpRom backToBInPrime ; location to return to BInPrime BOutPrime move.l ExpandMem,a2 ; use ExpandMem instead of PortBVars move.l ExpandMemRec.emSerdVars(a2),a2 ; JmpRom backToBOutPrime ; location to return to BOutPrime BControl move.l ExpandMem,a2 ; use ExpandMem instead of PortBVars move.l ExpandMemRec.emSerdVars(a2),a2 ; JmpRom backToBControl ; location to return to BControl BStatus move.l ExpandMem,a2 ; use ExpandMem instead of PortBVars move.l ExpandMemRec.emSerdVars(a2),a2 ; JmpRom backToBStatus ; location to return to BStatus endproc ; ; End of Async.a Patch ;_________________________________________________________________________________________ <50><51> EVA ;_________________________________________________________________________________________ <49> 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. ; ;_________________________________________________________________________________________ ; QuantumWBlindPortable - patch to NewSCSIWBlind ; ; This code replaces the original SCSIWBlind 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 completely patch out the existing ; ROM and system patch code for blind writes. This includes the TIB interpeter and ; the blind data transfer routine. ; ; Input: reg a3 = base of SCSI read addr ; a6 = SCSI stack frame ; d7 = zero ; Opt noclr ; set optimization level to no clr <49> djw Proc Export QuantumWBlindPortable QuantumWBlindPortable ROMDataEnd Equ $006CEC ; This is the entry to the TIB interpeter for blind writes. Enable pseudo-dma mode ; for the duration of the write transaction. 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 ; Start of TIB interpreter @dataCommon move.l 8(a6),a1 ; get the TIB pointer bra.s @exec ; tighten loop by branching first @c_inc bsr.s FastWriteFix ; go to write blind routine bne.s @data_end ; if error, bail out add.l d1,scParam1(a1) ; increment the pointer ; FALL THROUGH to @next_cmd ; continue @next_cmd @c_nop ; also NOP, just skip the command add.w #scSize,a1 ; point to the next TIB instruction ; FALL THROUGH to @exec @exec move.w scOpcode(a1),d1 ; get the function opcode move.l scParam1(a1),a2 ; get the generic address move.l scParam2(a1),d2 ; get the generic count cmp.w #maxOpcode,d1 ; valid opcode ? bhi.s @c_badop ; return err if not add.w d1,d1 ; convert to table index jmp @JmpTable(pc,d1.w) ; jump to routine for opcode @JmpTable bra.s @c_badop ; 0 is not a valid opcode bra.s @c_inc ; 1 bra.s @c_noinc ; 2 bra.s @c_add ; 3 bra.s @c_move ; 4 bra.s @c_loop ; 5 bra.s @c_nop ; 6 bra.s @c_stop ; 7 nop ; 8 not valid ; fall through to @c_badop @c_badop moveq.l #scBadparmsErr,d0 ; bad opcode bra.s @data_end @c_noinc ; NOINC addr,count bsr.s FastWriteFix ; go to write blind routine bne.s @data_end ; if error, exit bra.s @next_cmd ; else process next command @c_add ; ADD addr,data add.l d2,(a2) ; the count added to the where bra.s @next_cmd ; process the next command @c_move ; MOVE addr1,addr2 move.l d2,a0 ; get the destination address move.l (a2),(a0) ; simple enough bra.s @next_cmd ; process the next command @c_loop ; LOOP relative addr,count tst.l d2 ; check for zero loop count beq.s @next_cmd ; if count is already zero, quit loop subq.l #1,d2 ; drop the count move.l d2,scParam2(a1) ; put the count back for next time beq.s @next_cmd ; if count exhausted, don't loop add.l a2,a1 ; modify the command pointer bra.s @exec ; and process the next command @c_stop moveq.l #noErr,d0 ; indicate no error ; FALL THROUGH to @data_end ; @data_end movea.l ROMBase,a0 ; get base of rom adda.l #ROMDataEnd,a0 ; add offset to SCSI mgr in rom jmp (a0) ; continue 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 weeded out in the calling routine (Transfer). ; ; Entry: d2 = number of bytes to transfer ; 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 @savedregs Reg d2-d4/a1-a2/a5 ; Setup for the transfer by installing our bus exception handler and saving ; registers. movem.l @savedregs,-(sp) lea.l sBSR(a3),a1 ; a1 = sBSR(a3) by convention lea @Done,a5 ; set a5 as return addr from bus error move.l BusErrVct,OldBusErrVct(a6) ; keep old vector lea @BusErrHandler,a0 ; get addr of exception handler move.l a0,BusErrVct ; install it in exception table move.l SCSIHsk,a0 ; point to addr for pseudo-dma (hhsk) adda.l #wroffs,a0 ; add in the write offset moveq.l #noErr,d0 ; assume no error move.l d2,d1 ; make a copy of the count - is it zero ? beq @Done ; no bytes to xfer - done ; 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. 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 @Done ; exit ; Perform the write to the SCSI chip. First align the bytes to words, 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 add.l d0,d2 ; adjust the byte count (d0 = neg) add.l d0,d0 ; adjust to word index jmp @Aligned(pc,d0.w) ; 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 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 add.w d0,d0 ; d0 = convert to index by 6 byte entries move.w d0,d3 ; ...d3 = original value*2 add.w d0,d0 ; ...d0 = original value*4 add.w d3,d0 ; ...d0 = original value*6 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(pc,d0.w) ; jump into the loop @CopyLoop move.l (a2)+,d0 ; ...fill d0 with 4 bytes movep.l d0,0(a0) ; ...write 4 bytes to SCSI port move.l (a2)+,d0 ; do this for 32 bytes movep.l d0,0(a0) move.l (a2)+,d0 movep.l d0,0(a0) move.l (a2)+,d0 movep.l d0,0(a0) move.l (a2)+,d0 movep.l d0,0(a0) move.l (a2)+,d0 movep.l d0,0(a0) move.l (a2)+,d0 movep.l d0,0(a0) move.l (a2)+,d0 movep.l d0,0(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 add.w d2,d2 ; jmp @Remaining(pc,d2.w) ; 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 #noErr,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 move.l OldBusErrVct(a6),BusErrVct ; restore previous Bus Error vector movem.l (sp)+,@savedregs tst.w d0 ; set the condition codes rts ; we're done ;_________________________________________________________________________________________ ; BusErrHandler - SCSI manager's bus exception handler ; ; Hardware handshaking data transfers require that the target peripheral be ready to ; receive or transmit a long word of data within 16 microseconds. Failure of the ; target to keep up will result in a bus error. In 68000 machines, no retries are ; possible so the transfer fails. It is up to the driver to retry. ; ; Determine whether the bus error belongs to the SCSI manager by examining the fault ; address. It should be an offset from the SCSIHsk base. ; ; Entry: a3 = base address of SCSI chip ; a5 = address to return to if bus exception ; a6 = SCSI mgr local stack frame ptr ; ; Output: d0 = error code ; @BusErrHandler move.l d0,-(sp) ; save d0 ; Access to a number of SCSI addresses could cause a bus exception. Mask off the low ; bits of the fault address to get the base address. If it matches the SCSI chip's ; base address moveq.l #$ffffff9c,d0 ; mask = $ffffff9c and.l 2(sp),d0 ; clear variable bits of the fault address cmp.l SCSIHsk,d0 ; was it a SCSI chip access ? beq.s @ourErr ; if so, start processing the bus error ; Bus exception caused by someone else - call original exception handler move.l (sp)+,d0 ; restore d0 move.l OldBusErrVct(a6),-(sp) ; jump to old bus error handler rts ; Pop group 0 bus exception stack frame from stack and replace it with a normal ; group 1 (3 word) frame. Place a new return address in the exception frame and RTE. @ourErr move.w 8(sp),d0 ; get sr from stack adda.w #7*2,sp ; dispose of the 7-word frame move.l a5, -(sp) ; new return address move.w d0,-(sp) ; sr value ; Determine whether this was a phase change or a device timeout from hardware handshaking moveq.l #scBusTOErr,d0 ; assume a slow peripheral btst.b #bREQ,sCSR(a3) ; is *REQ present ? beq.s @ErrorDone ; no *REQ - assume timeout error btst.b #bPM,sBSR(a3) ; phase change? bne.s @ErrorDone ; no phase change moveq.l #scPhaseErr,d0 ; return phase change error @ErrorDone rte ; 'return' from the fake exception Endp ; end scsi Opt all ; set optimization back to preset level <49> djw ;--------------------------------------------------------------------------------------------- <4> msh ; ; DrvTblAsahi - This icon data replaces the ROM based data in the Asahi Sony Driver because ; the machine icon is different than the original Portable. The format of the ; table and icon data is taken directly from the file "SonyIcon.a". Even though ; Asahi only supports one drive, three table entries are included to be sure. ; ;--------------------------------------------------------------------------------------------- <4> msh Proc Export DrvTblAsahi DrvTblAsahi ; Macintosh Asahi table <4> msh dc.w DisketteIcon-DrvTblAsahi ;drive 3 logical icon, dc.w ExtAsahiIcon-DrvTblAsahi ;physical icon, dc.w $0103 ;primary ext removable 800K Sony dc.w DisketteIcon-DrvTblAsahi ;drive 3 logical icon, dc.w ExtAsahiIcon-DrvTblAsahi ;physical icon, dc.w $0103 ;primary ext removable 800K Sony dc.w DisketteIcon-DrvTblAsahi ;drive 3 logical icon, dc.w ExtAsahiIcon-DrvTblAsahi ;physical icon, dc.w $0103 ;primary ext removable 800K Sony <4> msh ; Plain Sony Diskette icon ALIGN 2 ;force alignment so offsets are even <4> msh DisketteIcon dc.w $7FFF,$FFF8,$8100,$0104,$8100,$7102,$8100,$8901 dc.w $8100,$8901,$8100,$8901,$8100,$8901,$8100,$8901 dc.w $8100,$7101,$8100,$0101,$80FF,$FE01,$8000,$0001 dc.w $8000,$0001,$8000,$0001,$8000,$0001,$8000,$0001 dc.w $8000,$0001,$8000,$0001,$87FF,$FFE1,$8800,$0011 dc.w $8800,$0011,$8800,$0011,$8800,$0011,$8800,$0011 dc.w $8800,$0011,$8800,$0011,$8800,$0011,$8800,$0011 dc.w $8800,$0011,$8800,$0011,$8800,$0011,$7FFF,$FFFE dc.w $7FFF,$FFF8,$FFFF,$FFFC,$FFFF,$FFFE,$FFFF,$FFFF dc.w $FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF dc.w $FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF dc.w $FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF dc.w $FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF dc.w $FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF dc.w $FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF dc.w $FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$7FFF,$FFFE dc.w $0 ;old HD-20 driver drive ID string (null here) ; External Floppy icon (Asahi only supports an external drive) <4> msh ExtAsahiIcon dc.w $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000 dc.w $0000,$0000,$0000,$0000,$0000,$0004,$0000,$000A dc.w $0000,$0012,$0000,$0024,$0000,$0048,$0000,$0090 dc.w $0000,$0120,$0000,$0240,$0000,$0480,$0000,$0900 dc.w $0000,$1200,$0000,$1400,$006D,$BC00,$00FF,$E400 dc.w $1F00,$0400,$2000,$0400,$3FFF,$F800,$0000,$0000 dc.w $0000,$0000,$007F,$FC40,$0040,$04C0,$004F,$E5FC dc.w $0040,$04C0,$007F,$FC40,$0000,$0000,$0000,$0000 dc.w $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000 dc.w $0000,$0000,$0000,$0000,$0000,$0004,$0000,$000E dc.w $0000,$001E,$0000,$003C,$0000,$0078,$0000,$00F0 dc.w $0000,$01E0,$0000,$03C0,$0000,$0780,$0000,$0F00 dc.w $0000,$1E00,$0000,$1C00,$006D,$BC00,$00FF,$FC00 dc.w $1FFF,$FC00,$3FFF,$FC00,$3FFF,$F800,$0000,$0000 dc.w $0000,$0000,$007F,$FC40,$007F,$FCC0,$007F,$FDFC dc.w $007F,$FCC0,$007F,$FC40,$0000,$0000,$0000,$0000 dc.w $0 ;old HD-20 driver drive ID string (null here) endp EndOfPatch PROC EXPORT ;######################################################################################### ;############################### INSTALL CODE GOES HERE ################################## ;######################################################################################### PatchInit PROC EXPORT IMPORT EndOfPatch,StartPatch,Cutback IMPORT FixupTbl ; <3.6> IMPORT DrvTblAsahi ; <4> msh MOVE.L D1,-(SP) ; Save our handle ;____________________________________________________________________________ ; Fixup patch addresses ; added <3.6> ; ; 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 ;######################################################################################### ;################################ BEGIN PATCH INSTALLS ################################### ;######################################################################################### ;----------------------------------------------------------------------------------------- ; ; Begin startup initialization ; ;----------------------------------------------------------------------------------------- ;------------------------------------------------------------------------------------ <2> SAM ; The Portable and the "Its a Sony!" Derringer have the same ROM but have different ; features. We need to distiguish between the two (ie change box flag & Gestalt). ;------------------------------------------------------------------------------------ MOVE.L ROMBase,A0 ; Get base of ROM CMPI.W #$11F1,18(A0) ; Is this a (Sony) Asahi? (ROM release number) 1.1f1 BNE.S @Portable ; -> Nope, do nothing MOVE.B #boxPowerBook100,boxFlag ; Slam boxFlag (Gestalt will use this when it gets loaded) <64> MOVE.L SonyVars,A0 ; To replace the floppy drive icons, LEA DrvTblAsahi,A1 ; insert pointer to new table directly MOVE.L A1,DrvTblPtr(A0) ; into Sony variables @Portable IMPORT ATPPatch ; 12/13/89 ATPpatchInstall MOVEA.L AGBHandle,A0 CMP.L #-1,A0 ; has it been set up yet? BNE.S @haveAGB ; yes MOVEQ #AGBSize,D0 ; D0 = size of RAM we need for AGB _NewHandle ,SYS,CLEAR ; vars are all zero'd BNE @atpinstalldone ; return on error MOVE.L A0,AGBHandle @haveAGB MOVEA.L (A0),A0 ; A0->AGB PEA ATPPatch MOVE.L (SP)+,atpHook(A0) @atpinstalldone ; ;********************* Start of SANE Package Optimization ********************* GGD <2.6><3.5><5.7> ;_______________________________________________________________________ ; 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. ;_______________________________________________________________________ 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 ;********************* End of SANE Package Optimization ********************* GGD <2.6> ;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ <56> ; 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 Portable ROMs OR in the GestaltPatches.a file... The changes are not ; trivial, so weÕre punting and loading the Gestalt ptch on Portable ROMs, too... ; ; Before we do, though, we throw away any storage that Gestalt has allocated. ; move.l ExpandMem, a0 move.l ExpandMemRec.emGestalt(a0), a0 ; get GestaltÕs pointer _DisposPtr ; now throw away the old pointer move.l GestaltGlobals.longH(a0), a0 ; get the table handle _DisposHandle ; and toss it away! PtchInst 5 ; Gestalt ptch ;----------------------------------------------------------------------------------------- ; ; <3.1> 8/10/89 CCH - This installs the Gestalt location error patch. ; ;----------------------------------------------------------------------------------------- import gestaltPatch,gestaltAddr stuffOldTrap gestaltAddr,GestaltTrapID setTrap gestaltPatch,GestaltTrapID ;----------------------------------------------------------------------------------------- ; ; <3.0> 8/10/89 CCH - This installs/modifies various Gestalt functions that changed ; after the Esprit ROM went final. ; ;----------------------------------------------------------------------------------------- gestaltRBVAddr EQU 'rbv ' gestaltSCCReadAddr EQU 'sccr' gestaltSCCWriteAddr EQU 'sccw' gestaltVIA1Addr EQU 'via1' gestaltVIA2Addr EQU 'via2' gestaltSlotAttr EQU 'slot' ; <40> gestaltSlotCount EQU 'nubs' ; <40> gestaltFirstSlot EQU 'slt1' ; <40> import gestaltParity,gestaltLowMem,gestaltQDVers lea gestaltNBCon,a0 ; address of gestaltNuBusConnectors patch <39> move.l #gestaltNuBusConnectors,d0 ; selector to ADD _NewGestalt lea gestaltSerial,a0 ; address of gestaltSerialAttr patch <39> move.l #gestaltSerialAttr,d0 ; selector to ADD _NewGestalt lea gestaltParity,a0 ; address of gestaltParityAttr patch move.l #gestaltParityAttr,d0 ; selector to ADD _NewGestalt lea gestaltLowMem,a0 ; address of gestaltLowMemSize patch move.l #gestaltLowMemorySize,d0 ; selector to ADD _NewGestalt lea gestaltQDVers,a0 ; address of gestaltQDVersion patch move.l #gestaltQuickdrawVersion,d0 ; selector to REPLACE _ReplaceGestalt lea gestaltMisc,a0 ; addr of gestaltMisc patch move.l #gestaltMiscAttr,d0 ; selector to ADD _NewGestalt lea gestaltNMgr,a0 ; addr of gestaltNotificationMgrAttr patch move.l #gestaltNotificationMgrAttr,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 lea gestaltUndef,a0 ; addr of gestaltUndef patch <40> move.l #gestaltSlotAttr,d0 ; selector to REPLACE _ReplaceGestalt lea gestaltUndef,a0 ; addr of gestaltUndef patch <40> move.l #gestaltSlotCount,d0 ; selector to REPLACE _ReplaceGestalt lea gestaltUndef,a0 ; addr of gestaltUndef patch <40> move.l #gestaltFirstSlot,d0 ; selector to REPLACE _ReplaceGestalt ;----------------------------------------------------------------------------------------- IF doScriptMgrGestalt AND (NOT installScriptMgrPtch27) THEN ; <4.6><15> ;********* start of Gestalt install for Script Mgr <2.7> <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 ;********** end of Gestalt install for Script Mgr <2.7> <08/05/89 pke> ********** ENDIF ; <4.6> ;----------------------------------------------------------------------------------------- ; Install Menu Manager patches InstToolTp NewInitProcMenu,$8 ;________________________________________________________________ <3.7><08/21/89 pke> ; Patch to Pack6 to fix Script Manager routines ; IF doScriptMgrPack6Fix AND (NOT installScriptMgrPtch39) THEN ; <12><15> InstToolTp ptchPack6,$1ED ENDIF ;____________________________________________________________________________ pke <3.9> ; Install patches to UprString,CmpString,RelString InstOSTp NewUprString,$54 InstOSTp NewCmpString,$3C InstOSTp NewRelString,$50 ;____________________________________________________________________________ ; Bump Script Manager version number for IntlForce bug fix (SysVers < $700) pke <4.2> ; Set Script Manager version (SysVers >= $700) pke <4.4> ; redo using new symbol smgrVersPTCHRom pke <4.5> IF doScriptMgrSetROMVers AND (NOT installScriptMgrPtch39) THEN ; <12><15> With SMgrRecord GetSMgrCore a0 move.w #smgrVersPTCHRom,smgrVersion(a0) EndWith ENDIF ;____________________________________________________________________________ ; Initialize additional Script Manager vectors pke <4.3> ; Add CallInterface pke <4.5> ; Add NewSwapIcon (7.0 only, moved to ptch 39) pke <4.7> IF doScriptMgrNewVectors AND (NOT installScriptMgrPtch27) THEN ; <12><15> ROMSMgrCalcRect EQU $17C84 ROMSMgrInitFonts EQU $17CDE ROMCallInterface EQU $17E6A ; <4.5> With SMgrRecord GetSMgrCore a0 leaRom ROMSMgrCalcRect,a1 move.l a1,sVectSMgrCalcRect(a0) leaRom ROMSMgrInitFonts,a1 move.l a1,sVectSMgrInitFonts(a0) leaRom ROMCallInterface,a1 ; <4.5> move.l a1,sVectCallInterface(a0) ; <4.5> EndWith ENDIF ;____________________________________________________________________________ pke <4.4> ; Install Script Manager 7.0 extensions, ROM patches IF installScriptMgrPtch39 THEN ; <15> PtchInst 39 ; <12> ENDIF IF installScriptMgrPtch27 THEN ; <15> PtchInst 27 ; <4.4> ENDIF ;____________________________________________________________________________ pke <5.4> ; Install patches for Script Manager routines InitDateCache, String2Date IF doScriptMgrStr2DatFix AND (NOT installScriptMgrPtch39) THEN ; <12><15> 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 <5.5> ; 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 ; <12><15> PatchOSJump oldGetIndADB,$78 ; set addr for BackToTrap InstOSTp ptchGetIndADB,$78 ; Éand then install patch ENDIF ;____________________________________________________________________________ pke <5.9> ; Install Script Manager patch to LwrString so it handles 2-byte chars IF doScriptMgrLwrString2 AND (NOT installScriptMgrPtch27) THEN ; <5.9><15> PatchOSJump oldLwrString,$56 ; set addr for BackToTrap InstOSTp ptchLwrString,$56 ; Éand then install patch ENDIF ;____________________________________________________________________________ GMR <8> ; Install EDisk Prime patch, to properly update ioActCnt, dCtlPos properly ; after a read/write. EDiskPrimeInst eDiskRefNum equ -49 ; DRVR id = 48, refnum = -49 IMPORT HWDepRAM,HWDepROM,HWDepSLIM,vRAMExit,vROMExit,vSLIMExit WITH EDiskDriveInfo,EDiskVars move.l DrvQHdr+QHead,d0 ; get the drive queue head @loop beq.s @done ; if drive queue is empty movea.l d0,a0 ; a0 := drive queue element cmpi.w #EDiskRefNum,DQRefNum(a0) ; belong to an EDisk? beq.s @match @next move.l QLink(a0),d0 ; check next drive queue element bra.s @loop @match movea.l HWDepProcPtr(a0),a1 ; get old Proc ptr move.b DriveInfo+3(a0),d0 ; get disk type subi.b #16,d0 bne.s @romDisk lea HWDepRAM,a2 ; get ptr to start of new RAM proc cmp.l a1,a2 ; already patched this drive type? beq.s @next ; yes, skip move.l a1,vRAMExit+2-HWDepRAM(a2) ; tail patch old rtn into new rtn move.l a2,HWDepProcPtr(a0) ; stuff new proc ptr into globals bra.s @next @romDisk subq.b #1,d0 bne.s @slimDisk lea HWDepROM,a2 ; get ptr to start of new RAM proc cmp.l a1,a2 ; already patched this drive type? beq.s @next ; yes, skip move.l a1,vROMExit+2-HWDepROM(a2) ; tail patch old rtn into new rtn move.l a2,HWDepProcPtr(a0) ; stuff new proc ptr into globals bra.s @next @slimDisk subq.b #1,d0 bne.s @next ; not one we know about, try next drive lea HWDepSLIM,a2 ; get ptr to start of new RAM proc cmp.l a1,a2 ; already patched this drive type? beq.s @next ; yes, skip move.l a1,vSLIMExit+2-HWDepSLIM(a2) ; tail patch old rtn into new rtn move.l a2,HWDepProcPtr(a0) ; stuff new proc ptr into globals bra.s @next @done ENDWITH ;_________________________________________________________________________________________ EVA <50> ; Install Async Serial Driver Vector Address ; Install latesta version number for driver 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 ;_________________________________________________________________________________________ <49> djw ; Install the SCSI Manager patch for the Quantum 7.9 ROM fix Import QuantumWBlindPortable with scsiGlobalRecord movea.l SCSIGlobals,a1 ; get ptr to SCSI globals lea QuantumWBlindPortable,a0 ; a0 = TIB interpreter patch move.l a0,jvWBlind(a1) ; replace vector to blind write routine endwith ;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ ;############################### 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 ; PatchInstall code macro <1.6-4april89-CEL> Proc Export FixupTbl ;################## TABLE OF LOCATIONS TO BE OFFSET BY [ROMBase] ######### <3.6> pke ; ; 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