;__________________________________________________________________________________________________ ; ; File: SysUtil.a ; ; Contains: This file contains system utility core routines: ReadParam, WriteParam, ; ReadDateTime, SetDateTime, InitUtil, Delay, CmpString ; ; Written by: Larry Kenyon ; ; Copyright © 1982-1993 by Apple Computer, Inc. All rights reserved. ; ; Change History (most recent first): ; ; 10/25/93 SAM Roll in from mc900ftjesus. ; 10/25/93 SAM Changed InitUtil to explicitly set the memory manager PRAM ; location to a nonzero default (Figment on, 32 bit heaps). ; Changed the default mouse speed setting from 2 to 3. ; 6/21/93 SAM Changed the comparison in _Delay to be unsigned (ugh) and bumped ; the default disk cache size from 32 to 96k. ; 6/14/93 kc Roll in Ludwig. ; 6/11/93 chp Replace the Reliability Manager’s Time Manager task with a ; _DTInstall of the original task code. It is better to call ; _ReadXPram and _WriteXPram with interrupts enabled since ; interrupts are used to communicate with Egret/CUDA. ; 1/29/93 RB Made the Delay trap compatible with NuKernel by changing the way ; it uses the status register. ; 10/18/92 CCH Added NoSound conditional for build-time zeroing of volume. ; 9/28/92 RB The old Sound Manager used to update the low mem global ; sdVolume, but the new one does not. So I chose the ReadPram and ; WritePRam routines to update sdVolume after the volume level is ; changed by the Control Panel, which writes PRAM. Removed the ; NoSound code used for Cyclone bringup. ; 6/29/92 RB Re-enable sound for the New New Sound Manager. ; 5/28/92 kc Roll in Horror Changes. Comments Follow: ; 5/13/92 KW (HJR,H7) Fix problem in InitCPHardware where it was calling a ; RAMless routine without having the return address in A6. ; 02/12/92 jmp •••Temporarily set the default sound volume to zero to effectively••• ; disable sound on Cyclone. ;
11/12/91 jmp Just went back and marked my previous change. ;
11/12/91 jmp Changed the pRAM table to default to having the color desktop ; pattern enabled for CQD-capable CPUs. ;

11/6/91 SWC Re-wrote clock and PRAM routines to be table-driven so that ; future expansion should be really simple (and clean). Hardware ; dependent routines will now be found in ClockPRAMPrimitives.a. ;

10/18/91 SWC Exported ReadTime so the ROM will link (changes in progress ; caused a little problem with sources out of sync). ;

8/6/91 SWC Modified ReadPRAM and WritePRAM so they use extended PRAM calls ; to get the original 20 PRAM bytes. ; 5/21/92 kc Append "Trap" to the names of ; SysEnvirons,WriteParam,ReadDateTime,SetDateTime,UprString and ; RelString to avoid name conflict with the glue. ; <10> 9/9/91 JSM Cleanup header, use SysEnvirons stuff defined in SysEqu.a ; instead of redefining it here. ; <9> 6/12/91 LN Changed #include 'HardwareEqu.a' to 'HardwarePrivateEqu.a' ; <8> 7/23/90 MSH WriteParam did the read back verify all wrong. ; <7> 3/22/90 MSH SysUtil and Clock rewritten to place all hardware dependent ; routines in clock and to remove redundant parameter RAM reading ; and writing routines. Also added Waimea versions of these ; routines. ; <6> 2/28/90 GMR Made changes for Egret code to match new Egret equates. ; <5> 2/10/90 GMR Put in temporary fix for Egret, using Wr6805Addr instead of ; WrPram. ; <4> 2/5/90 GMR Added Egret clock support to ReadTime, WriteTime, and ReadPram, ; WritePram, making them universal. ; <3> 1/3/90 CCH Changed Gestalt equate filename back to GestaltEqu.a. ; <2> 1/2/90 CCH Changed name of Gestalt equate file. ; <3.7> 11/13/89 MSH Pmgr equates now in record format. ; <3.6> 8/28/89 PKE Delete LwrString from this file and just use the one in the ; Script Manager file ScriptMgrPAtch.a (same code, no sense in ; duplicating it here; should have done this a long time ago). ; Also delete include of PackMacs.a, ScriptPriv.a. ; <3.5> 8/27/89 PKE Deleted local newItl2Tables symbol (used for LwrString, was set ; to 1 here) and cleaned up conditionals based on it. ; <3.4> 8/24/89 PKE FOR F-19, WE SHOULD DO CHANGE #2 HERE: Rolling in changes from ; patch files: (1) Change LwrString to save IntlForce flag then ; clear it before IUGetIntl call, restoring it afterward. This is ; so we get the itl2 tables for the correct script (instead of the ; tables for the system script). (2) Put UpperTab bug back in (was ; removed in 1.5) so file system sorting via RelString works on ; old volumes. ; <3.3> 8/22/89 SES Removed references to nFiles. Changed EnvBadSel & EnvSelTooBig ; to EnvBadVers and EnvVersTooBig. ; <3.2> 8/9/89 CCH Changed gestaltQuickdrawType to gestaltQuickdrawVersion. ; <3.1> 7/16/89 CCH NEEDED FOR AURORA: Made SysEnvirons check Gestalt error codes. ; <3.0> 7/8/89 PKE NEEDED FOR AURORA: Fixed error code returned by LwrString if ; 'itl2' not found. ; <2.9> 6/20/89 SWC Changed default mouse tracking from 0 (tablet) to 3 ; (medium-slow) so the mouse won't move like a slug when parameter ; RAM gets reset. Also to make Ed Birss happy, I hear. ; <2.8> 6/14/89 SWC Missed an '@' on a label. I know: "bad dog!" ; <2.7> 6/14/89 SWC Exported PRAMInit and PRAMInitTbl so they can be used by ; ValidatePRAM (Clock.a). Reformatted the PRAMInit table to make ; it more readable. Cleaned up code. ; <2.6> 6/5/89 PKE In LwrString, add more error checking after IUGetIntl call and ; set error return if necessary. ; <2.5> 5/25/89 CCH Revised again to deal with new Gestalt equates. ; <2.4> 5/25/89 rwh added the aptly named Reliability Manager ; <2.3> 5/24/89 GGD Converted to feature based conditionals. ; <2.2> 5/23/89 CCH Added check of Gestalt return codes to detect unknown results. ; <2.1> 5/18/89 CCH Updated SysEnvirons to use new Gestalt interface. ; <2.0> 4/16/89 CCH Changed Gestalt equates to new prefix convention. ; <1.9> 4/7/89 PKE Updated LwrString to use noMarkListOffset instead of ; lowerNoMarkListOffset. ; <1.8> 3/28/89 PKE Use OS trap bits 9-10 to control function of LwrString ; <1.7> 3/6/89 CCH Fix some minor bugs in SysEnvirons. ; <1.6> 3/3/89 CCH Gutted SysEnvirons, and replaced it with calls to Gestalt. ; <1.5> 3/1/89 PKE Save & restore a2 in LwrString; fixed err in UpperTab (UprString ; gave 'a' as the uppercase of '`'). ; <1.4> 2/28/89 PKE Revert UprString to version from Mac IIx ROMs, which doesn't ; move memory or depend on a5 world (the planned version could ; have done both). ; <1.3> 2/21/89 PKE Fix LwrString/UprString to get char class & case conversion ; tables from itl2, not itlR (itlR is going away and these tables ; are being moved to a newly extended itl2). Note: changing ; UprString to get tables from any resource could break apps, so ; it will be reverted to to an old, non-International version as ; soon as I find the old source. All the Intl stuff will be done ; thru enhancements to LwrString. ; <1.2> 1/16/89 GGD Added a scratch register parameter to the BigJSR macro calls ; since it will be needed when they change to use PC relative ; addressing. ; <1.1> 11/10/88 CCH Fixed Header. ; <1.0> 11/9/88 CCH Adding to EASE. ; <1.2> 10/27/88 PKE modified by Carl Hewitt and Brian McGhie as part of the process ; of putting Script Manager in ROM ; <•1.1> 9/23/88 CCH Got rid of inc.sum.d and empty nFiles ; <1.0> 2/10/88 BBM Adding file for the first time into EASE… ; 12/2/87 JTC Add SysEnvirons trap from patches as new PROC here. ; 10/29/87 rwh Port to Modern Victorian ; 10/27/87 MSH Bug fixes and added a retry to writetime. ; 9/3/87 MSH Port to HcMac (Laguna). Also removed some leftover trash at the ; end of the file. ; 2/9/87 SHF Changed parameter RAM initialization value for boot device: now ; defaults to SCSI ID 0 (internal). ; 12/19/86 GWN Extended PRAM init table. ; 12/12/86 GWN Replaced 'Bugs' with 'NuMc' to determine when PRAM is to be ; initialized with the data in PRAMInitTbl (instead of zeros). ; 11/7/86 bbm added an async patch mech. ; 10/9/86 bbm Modified to mpw aincludes. ; 2/19/86 BBM Made some modifications to work under MPW ; 10/30/85 LAK Incorporated init of new parameter RAM into InitUtil. Set bit 5 ; (13) of Hardware vector if parameter RAM was valid at boot. ; 10/3/85 BBM added three new Defs for new clock.text ; 7/24/85 RDC Deleted ClkRW routine (moved to new Clock.text) Changed BSR to ; JSR for ref's to ClkRW routine ; 6/7/85 JTC Modified to return long to OS dispatcher. <07Jun85> ; 2/27/85 JTC Add RelString to return -1,0,1 (<,=,>) rather than simply 0,1. ; Increase size, but speed, too. Marked... <27Feb85> ; 1/31/85 LAK Removed false RTE. Exclude all ints when talking to clock chip. ; 1/23/85 LAK Adapted for new equate files. ; 9/5/83 SC Changed default volume control to 3; changed init. ; 8/22/83 LAK Init port A parameter RAM to 9600 baud, etc. ; 8/21/83 SC Fixed "" "". ; 8/20/83 LAK Added new parameter ram stuff and changed init. ; 8/17/83 JTC changed CmpString, UprString for international character sets. ; 8/17/83 LAK initutil nolonger mucks with the time if param ram check byte is ; invalid. serial port a is no longer initialized to async. ; 5/25/83 LAK changed CmpString, UprString to general-purpose string ; operators. ; 4/29/83 LAK changed param ram cksum byte to $A6 to reset all machines. ; 4/27/83 LAK corrected serial port init values for 2 stop bit (not 1 1/2) ; 4/19/83 LAK added UprString routine; put in SCC config values for default ; param mem init (9600 baud, 8 data, 2 stop, no parity: both ; ports). ; 4/4/83 AJH changed initial value of misc2 param byte ; 3/10/83 LAK Updated defaults for font, menu flash, volume control. ; 3/8/83 LAK Fixed bug in Delay. ; 3/3/83 LAK Updated documentation on CmpString. ; 2/17/83 LAK ReadParam and WriteParam now preserve A2. InitUtil writes ; initial values to clock chip if it was not initialized. Added ; read verify to WriteParam. InitUtil is now a trap and observes ; Pascal regsave conventions. ; 2/10/83 LAK moved clock chip r/w procs here from boot code. ; 2/4/83 LAK put delay back in. ; 1/12/83 LAK removed Alert, Delay, and CoreWakeUp. ; 6/10/82 LAK SetDateTime now sets CLasTime to Ticks value. ; 6/9/82 ALO added Alert proc ; 6/7/82 LAK added an initialization routine which reads the clock. ; 5/27/82 LAK changed ReadDateTime, SetDateTime to use keyboard driver to do ; the work; ReadParam, WriteParam, ReadDateTime, SetDateTime ; interfaces have all been changed. ; 5/26/82 LAK changed ReadParam to read copy in memory instead of clock ram ; changed WriteParam to use keyboard driver to do the work ;__________________________________________________________________________________________________ BLANKS ON STRING ASIS LOAD 'StandardEqu.d' INCLUDE 'HardwarePrivateEqu.a' INCLUDE 'InternalOnlyEqu.a' INCLUDE 'GestaltEqu.a' INCLUDE 'IOPrimitiveEqu.a' INCLUDE 'ReliabilityEqu.a' INCLUDE 'UniversalEqu.a' IF &TYPE('NoSound') = 'UNDEFINED' THEN NoSound EQU 0 ; If conditional isn't set, default to sound on ENDIF SysUtil PROC EXPORT EXPORT ReadParam,WriteParamTrap,ReadDateTimeTrap,SetDateTimeTrap EXPORT InitUtil,DelayTrap,CmpString,UprStringTrap,RelStringTrap EXPORT ASyncPatch EXPORT PRAMINITTBL,PRAMINIT,READTIME PRINT NOGEN ;______________________________________________________________________ ; ; Routine: ASyncPatch ; Arguments: none ; Function: none ; ;______________________________________________________________________ ASyncPatch ; rts ; ;______________________________________________________________________ ; ; Routine: ReadParam ; A0 (input) -- pointer to buffer which returns parameters ; D0 (input) -- bits 0-19 indicate which of parameter bytes ; 0-19 to return in the buffer. bytes are ; returned in 0-19 order. ; Arguments: D0 (output) -- result code ; Function: This routine returns the requested bytes from the copy ; of parameter ram kept in low memory (SysParam). ; ;______________________________________________________________________ ReadParam LEA SysParam,A1 ; ptr to parameter ram copy in memory BSR.S XferPRam ; return requested bytes MOVEQ #0,D0 ; never any errors RTS XferPRam MOVEQ #20-1,D2 ; D2 is the loop counter (for 20 bytes . . .) XPLoop LSR.L #1,D0 ; read a byte for each one set BCC.S @1 ; skip if bit is not set MOVE.B (A1),(A0)+ ; load the next byte in return buffer @1 ADDQ.L #1,A1 ; incr pointer into parameter ram DBRA D2,XPLoop RTS ;______________________________________________________________________ ; ; Routine: WriteParam ; Input: A0 (input) -- pointer to PRAM buffer ; Arguments: D0 (output) -- result code ; Function: This routine writes the parameter ram copy in SysParam ; to the clock chip and then reads it back to verify. ;______________________________________________________________________ WriteParamTrap MOVEM.L A0/A1,-(SP) ; save copy of original pointer BSR WritePram ; write out SysParam to the chip <30Oct85> LAK LEA GetParam,A1 ; now read it back to verify BSR ReadPram ; use our special scratch area LEA SysParam,A0 ; point to original data MOVEQ #PRWrErr,D0 ; assume parameter ram write error MOVEQ #20/4-1,D2 ; loop count for 5 longs @2 CMPM.L (A0)+,(A1)+ BNE.S @3 ; exit on compare error DBRA D2,@2 MOVEQ #0,D0 ; no errors @3 MOVEM.L (SP)+,A0/A1 ; restore copy of original pointer RTS ;______________________________________________________________________ ; ; Routine: ReadDateTime ; A0 (input) -- pointer to buffer in which time is returned ; Arguments: D0 (output) -- result code ; Function: This routine updates Time in memory and then writes ; it out to the clock chip. ; ;______________________________________________________________________ ReadDateTimeTrap BSR ReadTime MOVE.L Time,(A0) ; give it back to requester in buffer RTS ;______________________________________________________________________ ; ; Routine: SetDateTime ; Arguments: D0 (input) -- 32-bit value to write to clock ; D0 (output) -- result code ; Function: This routine updates Time in memory and then writes ; it out to the clock chip. ; ;______________________________________________________________________ SetDateTimeTrap MOVE.L D0,Time ; update the time variable in memory BRA WriteTime ; ;______________________________________________________________________ ; ; Routine: Delay ; Arguments: A0 (input) -- number of tick counts to delay ; D0 (output) -- value of Ticks after delay ; interrupt level 0 is set ; Function: Delay is a simple routine which just waits the ; specified number of ticks (each tick is 1/60 second). ; ;______________________________________________________________________ DelayTrap ANDI.W #$F8FF,SR ; have to let interrupts in rb MOVE.L Ticks,D0 ADD.L A0,D0 @1 CMP.L Ticks,D0 ; have enough ticks ticked? BHI.S @1 ; -> No. Keep waiting. (now use unsigned comparison) RTS ;______________________________________________________________________ ; ; 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. ; ; Reverted to this version from Mac IIx ROMs; removing .S on a BRA and BSR <02/28/89 pke> ;______________________________________________________________________ UprStringTrap ; ; Register usage: ; D0 = string length = loop index ; D1 = trap opcode, with booleans ; D2 = string input/output buffer ; ; A0 = string 0 pointer ; BSR EntString ; changed BRA.S USLoopEntry USLoopTop ; ; Get next character, canonize it, and replace it. ; MOVE.B (A0),D2 BSR.S Canonizer MOVE.B D2,(A0)+ USLoopEntry DBRA D0,USLoopTop MOVEQ #0,D0 ; don't risk interp of error BRA ExtString ;______________________________________________________________________ <27Feb85>... ; ; 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 <27Feb85> ; 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. ; CmpString 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 RelStringTrap ; count on CCR from last D0 store 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 ; RelStringTrap BSR.S EntString ; ; Prime D4 to be -1, 0, 1 according to string 0 being shorter, equal, longer than string 1. ; Get shorter string length into D0. ; MOVEQ #0,D4 ; presume they're equal MOVE.W D0,D2 ; str 1 length SWAP D0 ; str 0 length CMP.W D0,D2 ; str1len - str0len BEQ.S ICLoopEntry ; D4 and D1 OK! BHI.S ICStr1Long ; str1len > str0len (unsigned, of course, Holmes) MOVEQ #1,D4 ; str0 is longer MOVE.W D2,D0 ; get shorter length CMP.W D4,D4 ; set CCR to show EQ BRA.S ICLoopEntry ICStr1Long MOVEQ #-1,D4 CMP.W D4,D4 ; set CCR to show EQ BRA.S ICLoopEntry ; ; Get next characters, canonize, and compare them. ; *********** NOTE: Must enter loop at ICLoopEntry with CCR indicated EQ!!!! ********** ; ICLoopTop MOVEQ #0,D2 ; clear hi bits for Canonizer MOVE.B (A0)+,D2 BSR.S Canonizer ADD.W D2,D2 ; need word index MOVE.W 0(A3,D2.W),D3 ; D3.W := canonical string 0 char MOVEQ #0,D2 MOVE.B (A1)+,D2 BSR.S Canonizer ADD.W D2,D2 CMP.W 0(A3,D2.W),D3 ; string 0 char - string 1 char ICLoopEntry DBNE D0,ICLoopTop ; fall through if NE or exhausted ; ; Falling through means chars found unequal above, or shorter string exhausted. ; The DBNE leaves CCR untainted, so use it! ; BEQ.S ICEqual ; strings = to end; let D4 decide... BHI.S ICHigh MOVEQ #-1,D0 ; str0 < str1 BRA.S ICExit ICHigh MOVEQ #1,D4 ; str0 > str1, fall through... ICEqual MOVE.L D4,D0 ICExit BRA.S ExtString ;______________________________________________________________________ ; ; Utility Canonizer looks at bits in D1.W (Dxxx xxxx Cxx1 010x) ; maps the character in D2.B to some canonical form. ; ; Input: D2.B = character to be mapped, with high bits of D2.W zero. ; Output: D2.B ;______________________________________________________________________ Canonizer TST.W D1 ; MI-strip PL-keep BPL.S dontStrip MOVE.B StripTab(D2.W),D2 dontStrip TST.B D1 ; PL-upper MI-keep BMI.S dontUpper MOVE.B 0(A2,D2.W),D2 ; UpperTab in A2 dontUpper RTS ;______________________________________________________________________ ; ; 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 LEA CmpTab,A3 ; ; Opword = 1010 xCDx xxxx xxxx , where C=caseBit and D=diacBit. Align to form ; Dxxx xxxx Cxx1 010x to facilitate testing D and C. ; ROL.W #6,D1 ; Dxxx xxxx xx10 10xC ROR.B #1,D1 ; Dxxx xxxx Cxx1 010x MOVEQ #0,D2 ; clear hi bits for Canonizer RTS ExtString MOVEM.L (SP)+,D3-D4/A2-A3 RTS ; ; 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 ;_________________________________________________________________________________________________________ ; StripTab ; No diacriticals in low ASCII. dcrow $00 dcrow $10 dcrow $20 dcrow $30 dcrow $40 dcrow $50 dcrow $60 dcrow $70 ; Diacritical city. DC.B ('A'),( 'A'),( 'C'),( 'E'),( 'N'),( 'O'),( 'U'),( 'a') DC.B ('a'),( 'a'),( 'a'),( 'a'),( 'a'),( 'c'),( 'e'),( 'e') DC.B ('e'),( 'e'),( 'i'),( 'i'),( 'i'),( 'i'),( 'n'),( 'o') DC.B ('o'),( 'o'),( 'o'),( 'o'),( 'u'),( 'u'),( 'u'),( 'u') ; O-slash at end. crow $A0 DC.B $A8, $A9, $AA, $AB, $AC, $AD, $AE,( 'O') ; a-under, o-under, and o-slash. crow $B0 DC.B $B8, $B9, $BA,( 'a'),( 'o'), $BD, $BE,( 'o') ; Diacrits at end. crow $C0 DC.B $C8, $C9, $CA,( 'A'),( 'A'),( 'O'), $CE, $CF ; Beware of y-umlaut, CHANGE FROM MAC-1 crow $D0 DC.B ('y'), $D9, $DA, $DB, $DC, $DD, $DE, $DF dcrow $E0 dcrow $F0 ; End of StripTab ;_________________________________________________________________________________________________________ ;_________________________________________________________________________________________________________ ; 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. ; fixed bug in which "`" is upper-cased as "a" <02/29/89 pke> ; restored above bug, so "`" ($60) goes to "a" ($61); needed for HFS. <3.4><08/24/89 pke> DC.B $61,( 'A'),( 'B'),( 'C'),( 'D'),( 'E'),( 'F'),( 'G') 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 ;_________________________________________________________________________________________________________ ; ; Entries in the CmpTab are given as words, with the "root" char in the high byte, and ; fine tuning in the low byte. ; MACRO basec DC.B (&Syslst[1]),( $00) ENDM MACRO modc DC.B (&Syslst[1]),( &Syslst[2]) ENDM ; ; Macro baserow sets up a sequence of 8 base characters, that is, with modifier=0. ; It's handy for setting up the punctuation and alphabetic characters. ; Macro dbaserow just does two rows. ; MACRO baserow basec &Syslst[1] basec &Syslst[1]+1 basec &Syslst[1]+2 basec &Syslst[1]+3 basec &Syslst[1]+4 basec &Syslst[1]+5 basec &Syslst[1]+6 basec &Syslst[1]+7 ENDM MACRO dbaserow baserow &Syslst[1] baserow &Syslst[1]+8 ENDM ; ; Macro lower11 is a convenience for setting up two-byte entries for a sequence of 11 lower-case ; characters. There are two such sequences: 'a'-'k' and 'p'-'z'. ; MACRO lower11 modc &Syslst[1], $80 modc &Syslst[1]+1, $80 modc &Syslst[1]+2, $80 modc &Syslst[1]+3, $80 modc &Syslst[1]+4, $80 modc &Syslst[1]+5, $80 modc &Syslst[1]+6, $80 modc &Syslst[1]+7, $80 modc &Syslst[1]+8, $80 modc &Syslst[1]+9, $80 modc &Syslst[1]+$A, $80 ENDM ; ; Macro ldiac takes two args: a lower case vanilla alphabetic and the name of a diacritical. ; It sets up a two-byte table entry with the corresponding upper-case character and a low-order ; modifier of the form $80+n where small n depends upon the diacritical in question. They are ordered ; plain < acute < grave < circumflex < umlaut < tilde < circle < slash < cedilla < under < ligature ; in order to give as nearly the flavor of the international string comparisons as possible. ; MACRO ldiac .* DC.B (&Syslst[1]-$20) .* IF &Eval(&Syslst[2]) = 'acute' THEN DC.B ($82) ENDIF .* IF &Eval(&Syslst[2]) = 'grave' THEN DC.B ($84) ENDIF .* IF &Eval(&Syslst[2]) = 'circumflex' THEN DC.B ($86) ENDIF .* IF &Eval(&Syslst[2]) = 'umlaut' THEN DC.B ($88) ENDIF .* IF &Eval(&Syslst[2]) = 'tilde' THEN DC.B ($8A) ENDIF .* IF &Eval(&Syslst[2]) = 'circle' THEN DC.B ($8C) ENDIF .* IF &Eval(&Syslst[2]) = 'slash' THEN DC.B ($8E) ENDIF .* IF &Eval(&Syslst[2]) = 'cedilla' THEN DC.B ($90) ENDIF .* IF &Eval(&Syslst[2]) = 'under' THEN DC.B ($92) ENDIF .* IF &Eval(&Syslst[2]) = 'ligature' THEN DC.B ($94) ENDIF .* ENDM ; ; Macro udiac takes two args: an upper-case vanilla alphabetic and the name of a diacritical. ; It sets up a two-byte table entry with the upper-case character and a low-order ; modifier of the form n where small n depends upon the diacritical in question. They are ordered ; plain < acute < grave < circumflex < umlaut < tilde < circle < slash < under < ligature ; in order to give as nearly the flavor of the international string comparisons as possible. ; MACRO udiac .* DC.B (&Syslst[1]) .* IF &Eval(&Syslst[2]) = 'acute' THEN DC.B ($02) ENDIF .* IF &Eval(&Syslst[2]) = 'grave' THEN DC.B ($04) ENDIF .* IF &Eval(&Syslst[2]) = 'circumflex' THEN DC.B ($06) ENDIF .* IF &Eval(&Syslst[2]) = 'umlaut' THEN DC.B ($08) ENDIF .* IF &Eval(&Syslst[2]) = 'tilde' THEN DC.B ($0A) ENDIF .* IF &Eval(&Syslst[2]) = 'circle' THEN DC.B ($0C) ENDIF .* IF &Eval(&Syslst[2]) = 'slash' THEN DC.B ($0E) ENDIF .* IF &Eval(&Syslst[2]) = 'cedilla' THEN DC.B ($10) ENDIF .* IF &Eval(&Syslst[2]) = 'under' THEN DC.B ($12) ENDIF .* IF &Eval(&Syslst[2]) = 'ligature' THEN DC.B ($14) ENDIF .* ENDM ;_________________________________________________________________________________________________________ ; CmpTab ; The control characters are vanilla dbaserow $00 dbaserow $10 ; Punctuation, digits, and upper case are all base chars dbaserow $20 dbaserow $30 dbaserow $40 dbaserow $50 ; Map lower case up and use punctuation as base chars. basec $61 lower11 $41 modc $4C, $80 modc $4D, $80 modc $4E, $80 modc $4F, $80 lower11 $50 basec $7B basec $7C basec $7D basec $7E basec $7F ; Grotesque diacriticals! udiac 'A', 'umlaut' udiac 'A', 'circle' udiac 'C', 'cedilla' udiac 'E', 'acute' udiac 'N', 'tilde' udiac 'O', 'umlaut' udiac 'U', 'umlaut' ldiac 'a', 'acute' ldiac 'a', 'grave' ldiac 'a', 'circumflex' ldiac 'a', 'umlaut' ldiac 'a', 'tilde' ldiac 'a', 'circle' ldiac 'c', 'cedilla' ldiac 'e', 'acute' ldiac 'e', 'grave' ldiac 'e', 'circumflex' ldiac 'e', 'umlaut' ldiac 'i', 'acute' ldiac 'i', 'grave' ldiac 'i', 'circumflex' ldiac 'i', 'umlaut' ldiac 'n', 'tilde' ldiac 'o', 'acute' ldiac 'o', 'grave' ldiac 'o', 'circumflex' ldiac 'o', 'umlaut' ldiac 'o', 'tilde' ldiac 'u', 'acute' ldiac 'u', 'grave' ldiac 'u', 'circumflex' ldiac 'u', 'umlaut' ; Column $A is cool up to s-zet; then up to AE and O-slash. basec $A0 basec $A1 basec $A2 basec $A3 basec $A4 basec $A5 basec $A6 modc 'S', $82 basec $A8 basec $A9 basec $AA basec $AB basec $AC basec $AD udiac 'A', 'ligature' udiac 'O', 'slash' ; Column $B is cool up to last five. baserow $B0 basec $B8 basec $B9 basec $BA ldiac 'a', 'under' ldiac 'o', 'under' basec $BD ldiac 'a', 'ligature' ldiac 'o', 'slash' ; Column $C has quote special case, non-breaking space, and 5 diacs basec $C0 basec $C1 basec $C2 basec $C3 basec $C4 basec $C5 basec $C6 modc '"', $06 modc '"', $08 basec $C9 basec ' ', $02 udiac 'A', 'grave' udiac 'A', 'tilde' udiac 'O', 'tilde' udiac 'O', 'ligature' ldiac 'o', 'ligature' ; Column $D has quotes and y. basec $D0 basec $D1 modc '"', $02 modc '"', $04 modc $27, $02 modc $27, $04 basec $D6 basec $D7 ldiac 'y', 'umlaut' basec $D9 basec $DA basec $DB basec $DC basec $DD basec $DE basec $DF ; Columns $E and $F are vanilla dbaserow $E0 dbaserow $F0 ; End of CmpTab ;_________________________________________________________________________________________________________ ; the following are lower-level routines which actually access the clock chip ;_______________________________________________________________________ ; ; Routine: ReadPram ; ; Arguments: A1 (input) -- pointer to buffer where 20 bytes are placed ; all regs preserved ; ; Function: All 20 bytes clock pram are read into buffer. ; ; Notes: Disables VIA interrupts for long periods of time (60 usec). ;_______________________________________________________________________ ReadPram MOVE.L A0,-(SP) ;

MOVE.B SPVolCtl,D0 ; get the sound volume control rb ANDI.B #7,D0 ; and mask out the sound res ID rb MOVE.B D0,sdVolume ; now store it low mem rb MOVEA.L A1,A0 ;

MOVE.L #(16<<16)+(16<<0),D0 ; first 16 bytes are at extended PRAM address 16

_ReadXPRAM ;

LEA 16(A1),A0 ;

MOVE.L #(4<<16)+(8<<0),D0 ; last 4 bytes are at extended PRAM address 8

_ReadXPRAM ;

MOVEA.L (SP)+,A0 ;

RTS ;

;_______________________________________________________________________ ; ; Routine: InitUtil ; ; Arguments: D0 (output) -- result code (0 if clock was already initialized) ; ; Function: The clock ram and time are read and stored in the low-memory ; buffer used by the clock utility routines. If the clock ram ; validity bit is not $A8, the values in Time and SysParam are ; initialized. ;_______________________________________________________________________ InitUtil CLR.W -(SP) ; assume no reset of PRam values <30Oct85> LAK BSR InitCPHardware ; initialize the hardware, if necessary

LEA SysParam,A1 ; where parameter ram is read to BSR.S ReadPram ; read parameter ram and BSR ReadTime ; time into SysParam and Time MOVEQ #0,D0 ; assume valid clock data CMP.B #$A8,(A1) ; is the clock data valid? BEQ.S CkNewPram ; branch if so MOVE.W #PRInitErr,(SP) ; report non-zero result <30Oct85> LAK MOVEQ #4,D1 LEA PramInit,A0 ; point to initial values @1 MOVE.L (A0)+,(A1)+ ; set parameter ram to initial values DBRA D1,@1 BSR WritePram ; and put initial values into clk chip CkNewPram BTST #6,HWCfgFlags ; new clock chip present? <30oct85> BBM BEQ.S ClkXit ; exit if not <30oct85> BBM LEA GetParam,A0 ; get pointer to useful buffer <30oct85> BBM MOVE.L #$4000C,D0 ; Command to read 4 bytes at addr C <30oct85> BBM _ReadXPRam ; <30oct85> BBM MOVE.L #'NuMc',D1 ; put validity bytes into D1 CMP.L (A0),D1 ; is the extra parameter ram valid? <30oct85> BBM BEQ.S ClkXit ; exit if so <30oct85> BBM MOVE.W #PRInitErr,(SP) ; report non-zero result <30Oct85> LAK MOVE.L D1,(A0) ; store out true validity bytes <30oct85> BBM MOVE.L #$4000C,D0 ; Command to write 4 bytes at addr C <30oct85> BBM _WriteXPRam ; <30oct85> BBM MOVEQ #32,D1 ; starting address to clear out XPRam <30oct85> BBM @0 MOVEQ #4,D0 ; number of bytes to write SWAP D0 ; finish the command byte <30oct85> BBM MOVE.W D1,D0 ; get the current address in XPRam <30oct85> BBM CLR.L (A0) ; clear out the buffer <30oct85> BBM _WriteXPRam ; ADDQ.B #4,D1 ; get the next address to write to ... <30oct85> BBM ; we want wrap at 256!!!! <30oct85> BBM CMP.B #8,D1 ; Check if we wrote the last address <30oct85> BBM BNE.S @0 ; if not loop back untill we are done <30oct85> BBM MOVEM.L A1,-(SP) ;Save A1 LEA PRAMInitTbl,A0 ;Copy the data from the PRAMInit table. LEA GetParam,A1 ; into the GetParam buffer. MOVEQ #5-1,D0 ;Loop 5 times (20 bytes) @10 MOVE.L (A0)+,(A1)+ ;Copy 4 bytes DBRA D0,@10 ;Branch if not done. MOVE.L #$00140076,D0 ;Write 20 bytes beginning at PRAM address $76 LEA GetParam,A0 ; from the buffer _WriteXPRam ; into the PRAM. ; Write the default memory mgr flags to location $8A. Since this is the only xpram whose default ; is non zero, we write it explicitly (as opposed to writing a default table full of zeros) LEA MMFlags,A0 ; Point A0 at the Memory Manager flags lomem MOVE.B #MMFlagsDefault,(A0) ; Put the default MMFlags into MMFlags MOVE.L #MMPRAMloc,D0 ; Write MMFlags to PRAM _WriteXPRam ; Store it. MOVEM.L (SP)+,A1 ;Restore A1 ClkXit MOVE.W (SP)+,D0 ; pass back error code <30oct85> LAK BNE.S @1 ; br if we had to reset clock/pram <30oct85> LAK BSET #5,HWCfgFlags ; note the good values <30oct85> LAK @1 EXT.L D0 ; OS errors are long <30oct85> LAK RTS ; original 20-byte parameter RAM initialization values PRAMInit DC.B $A8 ; old PRAM validity byte <2.7> DC.B 0 ; AppleTalk node ID hint for modem port <2.7> DC.B 0 ; AppleTalk node ID hint for printer port <2.7> DC.B (0<<4)+(0<<0) ; serial port usage = neither port in use <2.7> ; port A config: <2.7> DC.W (3<<14)+ \ ; • stop bits = 2 <2.7> (0<<12)+ \ ; • parity = none <2.7> (3<<10)+ \ ; • data bits = 8 <2.7> (10<<0) ; • baud = 9600 <2.7> ; port B config: <2.7> DC.W (3<<14)+ \ ; • stop bits = 2 <2.7> (0<<12)+ \ ; • parity = none <2.7> (3<<10)+ \ ; • data bits = 8 <2.7> (10<<0) ; • baud = 9600 <2.7> DC.L 0 ; alarm time (midnight, January 1, 1904) <2.7> DC.W Geneva-1 ; application font number - 1 <2.7> DC.B ((24/4)<<4)+ \ ; • auto-key threshold = 24 ticks <2.7> (6/2) ; • auto-key rate = 6 ticks <2.7> DC.B 0 ; • printer connection = 0 (printer port) <2.7> If NoSound Then ; Kill Sound if build-time conditional is set. cch DC.B (0<<7)+ \ ; • alarm enable = 0 (disabled) (2<<3)+ \ ; • mouse tracking = 2 (medium slow) 0 ; • speaker volume = 0 (off!) Else DC.B (0<<7)+ \ ; • alarm enable = 0 (disabled) (3<<3)+ \ ; • mouse tracking = 3 (medium slow) 3 ; • speaker volume = 3 (medium) Endif DC.B ((32/4)<<4)+ \ ; • double-click time = 32 ticks <2.7> (32/4) ; • caret-blink time = 32 ticks <2.7> DC.B 3 ; ram cache size in 32K blocks (96k default) DC.B (1<<7)+ \ ; • color desk pattern = 1 (use if CQD around) <2.7>
(1<<6)+ \ ; • mouse scaling = 1 (on) <2.7> (0<<5)+ \ ; • cache active = 0 (not active) <2.7> (0<<4)+ \ ; • preferred boot disk = 0 (internal drive) <2.7> (3<<2) ; • menu blink = 3 <2.7> ;Start Manager PRAMInitTbl DC.B 00 ; [$76] Reserved. DC.B 01 ; [$77] Default OS. DC.W $FFFF,$FFDF ; [$78-$7B] Default boot. ;Sound Manager? DC.W 0 ; [$7C-$7D] Sound alert id ;Menu Manager? DC.B 0 ; [$7E] Hierar menu dsply DC.B 0 ; [$7F] Hierar menu drag ;Start Manager DC.W 0 ; [$80-$81] Default video. ;Quick Draw DC.W 0,0,0 ; [$82-$87] Default Hilite Color (black) ;Reserved DC.B 0,0 ; [$88-$89] ;________________________________________________________________________________________ ; ; Routine: ReadTime ; ; Inputs: none ; ; Outputs: D0 - result code ; "Time" contains the 32-bit time value read from the clock ; ; Trashes: 8 bytes at "GetParam" ; ; Function: reads the time from the realtime clock ;________________________________________________________________________________________ ReadTime MOVEM.L A0/A2-A3/D1-D2/D4-D5,-(SP) ;

MOVEQ #ClkRdErr,D0 ; assume an error

MOVEA.L UnivInfoPtr,A0 ; point to this machine's product info

ADDA.L ProductInfo.ClockPRAMPtr(A0),A0 ; and get the address of its clock/PRAM table

MOVE.L 4*cpReadTime(A0),D1 ; get the offset to the routine

BEQ.S @NoEntry ; -> this function is not supported

ADDA.L D1,A0 ; calculate the routine's address

JSR (A0) ; and call it

MOVE.L GetParam,Time ; save the time, good or bad

@NoEntry MOVEM.L (SP)+,A0/A2-A3/D1-D2/D4-D5 ;

TST.W D0 ; set condition codes (for WriteTime)

RTS ;

;________________________________________________________________________________________ ; ; Routine: WriteTime ; ; Inputs: "Time" contains the 32-bit time value to write to the clock ; ; Outputs: D0 - result code: 0 = no error ; -2 = clock read error ; -3 = time written did not verify ; ; Trashes: 8 bytes at "GetParam" ; ; Function: Writes the time to the realtime clock. The clock is read after write for ; verification; if verification fails, a second attempt is made to read the clock. ;________________________________________________________________________________________ WriteTime MOVEM.L A0/D1-D5,-(SP) ;

MOVEQ #ClkWrErr,D0 ; assume an error

MOVEA.L UnivInfoPtr,A0 ; point to this machine's product info

ADDA.L ProductInfo.ClockPRAMPtr(A0),A0 ; and get the address of its clock/PRAM table

MOVE.L 4*cpWriteTime(A0),D1 ; get the offset to the routine

BEQ.S @NoEntry ; -> this function is not supported

ADDA.L D1,A0 ; calculate the routine's address

JSR (A0) ; and call it

@NoEntry MOVEM.L (SP)+,A0/D1-D5 ;

RTS ;

;________________________________________________________________________________________ ; ; Routine: InitCPHardware ; ; Inputs: none ; ; Outputs: none ; ; Trashes: A0,A1,D0,D1,D2 ; ; Function: initializes the clock/PRAM hardware, if necessary ;________________________________________________________________________________________ InitCPHardware ;

MOVEM.L A2/A5/A6,-(SP) ;

MOVEA.L UnivInfoPtr,A1 ; point to this machine's product info

MOVEA.L A1,A0 ; and get the address of its clock/PRAM table

ADDA.L ProductInfo.ClockPRAMPtr(A0),A0 ;

MOVE.L 4*cpInitHardware(A0),D1 ; get the offset to the routine

BEQ.S @NoEntry ; -> this function is not supported

LEA @NoEntry,A6 ; set up return address ADDA.L D1,A0 ; calculate the routine's address

JMP (A0) ; and call it @NoEntry MOVEM.L (SP)+,A2/A5/A6 ;

RTS ;

;_______________________________________________________________________ ; ; Routine: WritePram ; ; Arguments: SysParam contains the 20 bytes to write. ; all regs preserved ; ; Function: Writes all 20 bytes of parameter ram from SysParam. ; ; Notes: disables VIA interrupts for long periods of time (60 usec) ; no verification of write data is done ;_______________________________________________________________________ WritePram MOVE.L A0,-(SP) ;

MOVE.B SPVolCtl,D0 ; get the sound volume control rb ANDI.B #7,D0 ; and mask out the sound res ID rb MOVE.B D0,sdVolume ; now store it low mem rb LEA SysParam,A0 ;

MOVE.L #(16<<16)+(16<<0),D0 ; first 16 bytes are at extended PRAM address 16

_WriteXPRAM ;

LEA SysParam+16,A0 ;

MOVE.L #(4<<16)+(8<<0),D0 ; last 4 bytes are at extended PRAM address 8

_WriteXPRAM ;

MOVEA.L (SP)+,A0 ;

RTS ;

ENDPROC ;SysUtil ;----------------------------------------------------------------------------- ; SysEnvirons call. ; ; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed ;AppleSystemPatch PatchIIROM.a 28Mar87 #PABM150 (SysEnvirons) (SysEnvirons) ; ; SysEnvirons -- an environs call ; ; *** Note ***: SysEnvirons now calls uses the Gestalt call to determine it's ; information. Previous versions still operate normally, however, ; the latest (and last) version is updated as Gestalt entries are updated. ; ; Register Usage: ; ; INPUT ; D0.W: Selector ; A0.L: Pointer to theWorld ; ; USAGE ; D0: scratch ; D1: holds requested version number ; D2: holds EnvErr ; A0: scratch ; A2: hold pointer to theWorld!!! Don't touch this ! ; ; OUTPUT ; D0.W: error code ; A0.L: pointer to theWorld ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------------------- ; FUNCTION SysEnvirons(VersionRequested: Integer; VAR theWorld: SysEnvRec): OSErr; SysEnvironsTrap PROC EXPORT ; ; Proc header moved up to clear up dupl ; label problems. ;----------------------------------------------------------------------------------------- ; Equates ;----------------------------------------------------------------------------------------- envTRUE EQU 1 ; IM V1 p.86: "Boolean value in bit 0" -- FALSE EQU 0 TheVersion EQU 2 ; Current version of this call MAXINT EQU $7fffffff ; max number SysWDProcID EQU 'ERIK' ; for use with OpenWD TwoBitsClear EQU $3FFF ; for compare below (two high bits clear) ;----------------------------------------------------------------------------------------- ; The code starts here ;----------------------------------------------------------------------------------------- WITH SysEnvRec ; <10> MOVEM.L A0/D2,-(SP) ; save regs MOVE.L A0,A2 ; Pointer to theWorld ;----------------------------------------------------------------------------------------- ; Check for negative selector, or for selector too high -- Selector is in D0 at this point ;----------------------------------------------------------------------------------------- MOVE.W #EnvBadVers,D2 ; assume error number in D2 <3.3> TST.W D0 ; test the selector BLE EXIT ; if less than or equal to zero, then exit MOVE.W #noErr,D2 ; error return, set to zero for now, MPW will generate CLR.W here MOVE.W D0,D1 ; save requested version number in D1 CMP.W #curSysEnvVers,D0 ; test to see if requested version was bigger than current version <10> BLE.S GetSize ; if not, then continue MOVE.W #EnvVersTooBig,D2 ; put error here, but continue <3.3> MOVE.W #SysEnvRec.size,D0 ; change this as versions increase (which they won't) <10> BRA.S ZeroWorld ; start filling in ;----------------------------------------------------------------------------------------- ;-> Since all the environment records for versions 1-2 are the same size, we can ; use the same size for all of them. ;----------------------------------------------------------------------------------------- GetSize MOVE.W #SysEnvRec.size,D0 ; for now, just do this <10> ;----------------------------------------------------------------------------------------- ; ZeroWorld ; routine to zero out bytes of record ; ; On Input: D0 == bytes to zero ; D1 == requested version ; A0 == pointer to the world ; A2 == (copy of) pointer to the world ; ; Register usage: ; A0 == copy of world pointer ;----------------------------------------------------------------------------------------- ZeroWorld ASR.W #1,D0 ;count by words SUBQ #1,D0 ;adjust for Debra ZeroLoop CLR.W (A0)+ ;clear next word DBRA D0,ZeroLoop ;loop till done. ; now we've zeroed out the record FillInWorld1 MOVE.W D1,environsVersion(A2) ; put in version number <10> ;----------------------------------------------------------------------------------------- ; Get MachineType -- assumes 4.1 and later will not even run on 64K ROMs ; so we don't need to check for XLs or even 64K ROM Macs ; WARNING -- if run on old ROMS, this will return Env512KE!! ; this also assumes that future Macs will have 8(ROMBase) > 0 ; ;-> Actually get this from _Gestalt. ;----------------------------------------------------------------------------------------- GetMachineType Move.l #gestaltMachineType,D0 ; ask for machine type _Gestalt ; ask gestalt for the info tst.w d0 ; any errors? Beq.s OkMach ; if not, return result moveq #envMachUnknown,A0 ; oh well, use SysEnvs bad way of saying unknown Bra.s SaveMach OkMach Sub.w #2,A0 ; convert gestalt result to sysEnv result SaveMach Move.w A0,machineType(A2) ; save the result in the record <10> ;----------------------------------------------------------------------------------------- ; SYSTEM VERSION code ;----------------------------------------------------------------------------------------- Move.l #gestaltSystemVersion,D0 ; ask for system version _Gestalt ; ask gestalt for the info tst.w d0 ; any errors? Beq.s @ok ; if not, return result sub.l a0,a0 ; otherwise, return zero @ok Move.w A0,systemVersion(A2) ; no problem, dude.. <10> ;----------------------------------------------------------------------------------------- ; Get Processor Stuff ;----------------------------------------------------------------------------------------- Move.l #gestaltProcessorType,D0 ; ask for processor type _Gestalt ; ask gestalt for the info tst.w d0 ; any errors? Beq.s OkProc ; if not, return result moveq #envCPUUnknown,A0 ; oh well, use SysEnvs bad way of saying unknown OkProc Move.w a0,processor(A2) ; save it <10> ;----------------------------------------------------------------------------------------- ; HasFPU ;----------------------------------------------------------------------------------------- Move.l #gestaltFPUType,D0 ; ask for fpu type _Gestalt ; ask gestalt for the info tst.w d0 ; any errors? bne.s NoFPU ; whoops move.l a0,d0 ; this will be nonzero if an FPU exists, else zero Beq.s NoFPU ; oh well.. entry is already zero Move.b #envTRUE,hasFPU(A2) ; cool, we have one <10> NoFPU ;----------------------------------------------------------------------------------------- ; Has ColorQD ;----------------------------------------------------------------------------------------- ColorQD Move.l #gestaltQuickdrawVersion,D0 ; ask for QD version _Gestalt ; ask gestalt for the info tst.w d0 ; any errors? bne.s NoCQD ; whoops move.l a0,d0 ; this will be nonzero if CQD exists, else zero Beq.s NoCQD ; oh well.. entry is already zero MOVE.B #envTRUE,hasColorQD(A2) ; <10> NoCQD ;----------------------------------------------------------------------------------------- ; Get Keyboard type ;----------------------------------------------------------------------------------------- Move.l #gestaltKeyboardType,D0 ; ask for keyboard type _Gestalt ; ask gestalt for the info tst.w d0 ; any errors? Beq.s OkKeyBd ; whew.. moveq #envUnknownKbd,A0 ; oh well, use SysEnvs bad way of saying unknown OkKeyBd MOVE.W a0,keyBoardType(A2) ; move in the value and we're done <10> ;----------------------------------------------------------------------------------------- ; Get AppleTalk Driver Version Number ;----------------------------------------------------------------------------------------- Move.l #gestaltAppleTalkVersion,D0 ; ask for ATalk driver version num _Gestalt ; ask gestalt for the info tst.w d0 ; any errors? Beq.s @ok ; if not, return result sub.l a0,a0 ; otherwise, return zero @ok Move.w a0,atDrvrVersNum(A2) ; put version number in record <10> ;----------------------------------------------------------------------------------------- ; Get SysVRef -- returns WDRefNum of directory that contains ; open system file in D0 -- if this call fails, returns 0 ; We use GetFCBInfo here -- slower but smaller ; ; NOTE -- 4.1 will patch BootDrive code so BootDrive is always accurate ; we still need to use this method because DAs or unscrupulous ; apps may change BootDrive. ; ; Assumes system 4.1 and 128K or greater ROMs (HFS) ;----------------------------------------------------------------------------------------- getSysVRef Clr.l D0 ; in case we get an error below Move.w #(ioHVQElSize/2)-1,D1 ; this many CLR.Ws, minus one for the DBRA @1 Clr.w -(SP) ; push zeros on stack, worse case 2 too many. DBra D1,@1 ; branch if not done Move.l SP,A0 ; A0 points to cleared param blk for HFS calls Move.w SysMap,ioRefNum(A0) ; get the fileRefNum of System File _GetFCBInfo ; get info Bne.s FixStack ; oops, clean up stack and leave ; now we need to do a PBHGetVInfo call -- we've already established that we're running HFS Move.w ioFCBVRefNum(A0),ioVRefNum(A0) ; Thanks Bill B. -- no thanks Inside Mac _HGetVInfo ; get VFndrInfo (blessed folder's dirID) Bne.s FixStack ; oops, clean up stack and leave ; we're OK so far, now we just do a OpenWD, the VRef is set up we just need to ; get the id of the blessed folder from ioVFndrInfo[1] and put it into the dirID ; field of the parameter block, and away we go! VInfoOK Move.L ioVFndrInfo(A0),ioWDDirID(A0) ; set up the "blessed folder" Move.L #SysWDProcID,ioWDProcID(A0) ; put 'ERIK' into WDProcID _OpenWD ; open a working directory (probably already open?) Bne.s FixStack ; oops, clean up stack and leave Move.w ioVRefNum(A0),sysVRefNum(A2) ; put result in parameter block <10> FixStack Adda #ioHVQelSize,SP ; clean up the stack, same count as above. ;----------------------------------------------------------------------------------------- ; End of FillInWorld1 - for future versions (>=2) put checking in here to see how ; much more to fill in, based on selector passed in in D0 ;----------------------------------------------------------------------------------------- ENDWITH Exit MOVE.W D2,D0 ; put error number in D0 MOVEM.L (SP)+,A0/D2 ; restore regs, including A0 (pointer to record) RTS ; return to caller (Return address should be on stack) ENDPROC ; SysEnvirons ;----- <2.4> ; ; The Reliability Manager ; ; This new "manager" is responsible for monitoring the operation of the machine ; and recording pertinent information in parameter RAM. ; ; Written by Bob Herold, May 24, 1989 ; ;----- ;----- ; InitReliability - sets time of 1st power on, and initializes the Usage Statistics time ; manager task ; ; The time of 1st power on is kept as the number of 48 hour periods since Jan 1 1989. To ; calculate this, we first get the number of seconds since Jan 1 1989. On 020 and higher ; machines, we could divide by the number of seconds in 48 hours. To work on 68000 ; machines, we separate out factors of two to get the divisor into the 16 bit range: ; ; # 48 hrs since Jan 1 1989 = (# secs since Jan 1 1989) / (# secs in 48 hours) ; = (# secs) / (60 * 60 * 24 * 2) ; = (# secs) / (2*2*15) * (2*2*15) * (2*2*2*3) * 2 ; = (# secs) / (15 * 15 * 3) * 2^^8 ; = ((# secs) / 2^^8) / (15 * 15 * 3) ;--- InitReliability PROC EXPORT IMPORT RelTimeTask, RelDeferredTimeTask IF hasPowerMgr THEN rts ELSE ;--- ; Initialize the 'time of 1st power on' ;--- subq #RelPram>>16,sp ; allocate buffer on stack move.l Time,d1 ; get current # secs sub.l #Jan1st89,d1 ; get # secs since Jan 1 1989 blo.s @doneStart ; if earlier, clock chip set wrong! movea.l sp,a0 ; get buffer ptr move.l #RelPram,d0 ; get #, addr PRAM bytes _ReadXPram ; read 'em and weep move.l (sp),d0 ; get 'da bytes and.l #Rel1stMask,d0 ; mask all except 1st powered on time bne.s @doneStart ; if already set, do nothing lsr.l #8,d1 ; divide # secs by 2^^8 divu.w #15*15*3,d1 ; get # 48 hour periods (see comment above) moveq #Rel1stBit,d0 ; get shift count lsl.l d0,d1 ; shift our value into position and.l #Rel1stMask,d1 ; mask unneeded high bits and.l #-1-Rel1stMask,(sp) ; zero our bits in result or.l d1,(sp) ; overlay our value into result move.l #RelPram,d0 ; get #, addr PRAM bytes _WriteXPram ; write out 1st power on time @doneStart addq #RelPram>>16,sp ; de-allocate buffer ;--- ; Set up time manager task for power on time measurement ;--- WITH RelGlobals moveq #rlRecSize,d0 ; get size Reliability Mgr globals move.b d0,d1 ; save for later _NewPtr ,sys,clear ; allocate space for it bne.s @done ; don't bother if no room move.l ExpandMem,a1 ; get ptr to low memory expansion move.l a0,ExpandMemRec.emReliability(a1) ; save ptr to Reliability globals there move.b d1,rlGlobalsSize(a0) ; save size of globals move.b #rlRecVers,rlGlobalsVers(a0); save version number of globals bclr #usRelTaskRun,UnSwitchedFlags; signal we are timing ; Initialize a deferred task queue element to schedule execution of the original Time Manager ; task, now called RelDeferredTimeTask. Pass a pointer to the Time Manager task in dtParm so ; that the original code still gets its expected parameter in A1. move.w #dtQType,rlDeferredTask.qType(a0) lea RelDeferredTimeTask,a1 move.l a1,rlDeferredTask.dtAddr(a0) lea rlTimeBlock(a0),a1 move.l a1,rlDeferredTask.dtParm(a0) lea rlTimeBlock(a0),a0 ; point to time manager task block lea RelTimeTask,a1 ; point to our time task move.l a1,tmAddr(a0) ; stuff it into task block _InsXTime ; install our task move.l #RelMsCount,d0 ; get # ms between calls clr.l tmWakeUp(a0) ; signal its the first time _PrimeTime ; fire up time mgr task @done rts ENDWITH ; {RelGlobals} ENDIF ENDPROC ; {InitReliability} ;----- ; RelTimeTask - the time manager task for doing all this reliability stuff ; ; Called by the Time Manager ; ; Entry ; a0 - points to this routine (not too useful, huh?) ; a1 - points to task block (now there's something useful!) ; ; ; RelDeferredTimeTask - the deferred Time Manager task for doing all this reliability stuff ; ; Called by the Deferred Task Manager ; ; Entry ; A1 - dtParm points to the originating Time Manager task block ;--- RelTimeTask PROC EXPORT ; If PRAM is in Egret/CUDA, _ReadXPram and _WriteXPram require interrupts enabled ; to execute efficiently. Therefore, the periodic Reliability task now uses the ; Deferred Task Manager to be more interrupt-friendly. ; This helps MIDI SysEx dumps and other interrupt tasks run more punctually. lea tmXQSize(a1),a0 ; deferred task element follows TM task element _DTInstall rts entry RelDeferredTimeTask RelDeferredTimeTask subq #RelPram>>16,sp ; allocate buffer on stack movea.l sp,a0 ; get buffer ptr move.l #RelPram,d0 ; get #, addr PRAM bytes _ReadXPram ; read 'em and weep move.l (sp),d0 ; get 'da bytes move.l d0,d1 ; save a copy and.l #RelPwrMask,d0 ; mask to get power on time addq.l #1,d0 ; increment power on time and.l #RelPwrMask,d0 ; mask again, in case of rollover and.l #-1-RelPwrMask,d1 ; zero power on time bits or.l d0,d1 ; replace the power on time bits move.l d1,(a0) ; put new PRAM value in buffer move.l #RelPram,d0 ; get #, addr PRAM bytes _WriteXPRAM ; write 'em back addq #RelPram>>16,sp ; deallocate buffer move.l a1,a0 ; get ptr to task block move.l #RelMsCount,d0 ; get # ms between calls _PrimeTime ; re-fire up time mgr task rts ENDPROC ; {RelTimeTask} END