-not a Macintosh disk-FbGYa4GYa;0a:a4BH@%,țY1ןrwk    MW Source 10Pp 0Pp "0$P&p(*,.0204P8:<>@B0DPFHJLNPR0TPVpXZ\^`b0dPfphjlnpr0tPpxz|~0PpЎ  0 P p О  0 P p  ЮFNDRERIK@ rǟwkDeskTopTEXTMACAUaXgg| scrap.textTEXTMACA`dLhfkfsegloader.textTEXTMACA6f8fsetprefix.textTEXTMACA 7=@ff_ sony.textTEXTMACA0G Rff start.textTEXTMACA0`KMPf>fstartdiag.textTEXTMACA0_Z\f fstarthooks.textTEXTMACA0 vfࠟf_startinit.textTEXTMACA` 9<fifstartmain.textTEXTMACA`` /fϟf stub.textTEXTMACA` zf6fS vblcore.textSC01SCOM` X͟f?WorkshopDTR/Lisa RUUU""""D ` `DD```||CBC|~<~``D?? Finder 1.0n|+=@% 4 %< MW Source 1 4MACAICN#mwRTO9:WFREF/2V (%w#g@ "DA$H @@ $"ID?$@BHA 0"!N0!`@  @????@ ;==ۈwh(@ <?@ "DA$H @@ $"ID?$@BHA 0"!N0!`@  @????APPLWORDTEXTPRES,SCOMICN#'MWFREFd?w#N @@8@(/@ @ ;p111333111;<<@PP*P@???? @ q         qH UHUHUH @ q          qψ APPLSC01SC00 R$FSTR :FOBJFBNDLRMACAjICN#vFREFSCOM$% N$;%,g$X$l$}MW$y%('$u%4:W$ PO9$LRT$\mw$`$$?$d$$%$0t ($%xV$h/2$d$k MW Source 1; FILE Scrap.text ; MACWORKS Copy ;--------------------------------------------------------------- ; ; Mac Scrap Manager ; ; This is a set of simple routines to help the applications ; manipulate the scrap for inter-application cutting and pasting. ; ; The scrap is simply a collection of typed data objects(Hi Bruce). ; in a handle that is maintained through application launches. ; There are two "Universal types," TEXT, for vanilla text, and PICT, ; for QuickDraw pictures. However, the application is free to ; add private types like SYLK. ; ; The general rules of thumb are: applications MUST be able to ; read both universal types and write at least one. This should ; insure that all applications can minimally exchange information ; through at least one level. If applications choose to write more ; than one type, the order is important; one should write the types ; in order of importance to that application. eg. a word processor ; should write out its private format first, then text, then a picture ; if desired. This implicitly states which type has the highest ; information content coming from that particular application. When ; reading the scrap one should scan for the types in the same order ; in an attempt to recover the highest information content. ; ; There are user-defined "fields" in both the TEXT and PICT types so ; the applications are encouraged to place custom data there in an ; effort to reduce the size of the scrap. As in the example above, a ; word processor might hide its formatting information in the TEXT ; comments so that only two types are written into the scrap. ; ; The script for using the scrap is: The application starts up. It ; inquires as early as possible about the scrap to determine if there ; will be enough room for the application and scrap to coexist in the ; heap. If not, it calls an unload procedure to save the scrap to disk. ; If that fails, or is deemed impossible, an alert should be raised to ; inform the user and ask for guidance. The user might just want to ; abort the application at this point. ; ; Then the application must remember that the universal scrap is ; pregnant with data when a paste command is executed. At that point ; it should dissect the scrap to find the most logical type and ; paste that into its data. An alternative is to automatically ; convert the scrap to the applications internal format so that the ; paste code can be dumb and not have to serve two masters. It is ; important to realize that the scrap data cannot be dumped until a ; cut/copy-like command is executed. While the applications runs ; there is, of course, no need to maintain or otherwise diddle with ; the universal scrap. ; ; When the application terminates, it should make every attempt to ; dump its scrap into the universal one. Obviously, if the application ; has a disk based scrap, it may be impossible to copy into memory. ; Or even with a memory based scrap, there might not be enough room ; for a "second" copy in the heap. In either case an alert should ; be raised telling the user of the applications dilemma. The user ; might at this point stay in the application and prune the scrap. ; ; When the user activates or deactivates an ornament, a similar course ; should be followed by the application. The activate and deactivate ; events contain some additional bits in the modifiers field which will ; indicate whether the transition is between a system or application ; window. If this case is true and the event is a deactivate, the ; application should call the same code as the termination sequence ; above. Of course, activate events should then parallel the startup ; scenario. ; ; ; The routines are: ; ; ScrapStuff = RECORD ; scrapSize: LONGINT; ; scrapHandle: Handle; ; scrapCount: INTEGER; ; scrapState: INTEGER; ; scrapName: StringPtr; ; END; ; pScrapStuff: ^ ScrapStuff; ; FUNCTION InfoScrap: pScrapStuff; ; returns a pointer to the scrap info ; ; FUNCTION UnloadScrap: LONGINT; ; Unloads the scrap from memory ; ; FUNCTION LoadScrap: LONGINT; ; Loads the scrap from scrap file into memory ; ; FUNCTION GetScrap( hDest: Handle; what: ResType; ; VAR offset: LONGINT ): LONGINT; ; hDest = the destination handle in which to copy the object. ; If handle is NIL, then doesn't get it. ; what = the type of object to copy ; offset returned as offset in scrap of this object ; result is -1 if it couldn't be found or a negative system ; error; set >= 0 (to size) if OK ; ; FUNCTION ZeroScrap: LONGINT; ; Cuts back the scrap to empty. ; ; FUNCTION PutScrap( length: LONGINT; what: ResType; source: Ptr ): LONGINT; ; what = the type of object to copy ; source = pointer from which to copy the object ; length = length of object at source ; ; ; Modification history: ; ; 21-Aug-83 SC Crunched eight bytes out ; 29-Aug-83 SC Changed scrap info interface ; 05-Sep-83 SC Andy found a bug... ; 07-Sep-83 SC Added scrapCount ; ;--------------------------------------------------------------- .NOLIST .INCLUDE Tlasm-SYSEQU.TEXT .INCLUDE Tlasm-SYSMACS.TEXT .INCLUDE Tlasm-SYSERR.TEXT .INCLUDE Tlasm-ToolMACS.TEXT .INCLUDE Tlasm-ToolEQU.TEXT .LIST ; 3 States of scrap (In scrapState): negative uninitialized, positive on disk, ; zero in memory ; Defs for a scrap entry scrType .EQU 0 scrLength .EQU scrType+4 scrData .EQU scrLength+4 ; Std frame off A6 scrapIO .EQU -IOFQElSize ; io cmd dLength .EQU scrapIO-4 ; disk object length dType .EQU dLength-4 ; disk object type stdLink .EQU dType ; std frame size .PROC ScrapMgr,0 .DEF InfoScrap .DEF LoadScrap .DEF UnloadScrap .DEF GetScrap .DEF ZeroScrap .DEF PutScrap ;-----------------------------------Scrap----------------------------------- ; ; FUNCTION InfoScrap: pScrapStuff; ; ;-----------------------------------Scrap----------------------------------- ; InfoScrap MOVE.L (SP)+,A0 ; RTS LEA scrapVars,A1 MOVE.L A1,(SP) JMP (A0) ;-----------------------------------Scrap----------------------------------- ; ; StdEntry ; ; This routine sets up the standard frame and builds the ; io command block for an open. Then it tries to create and then open ; the file ; ; ; Exit: ; A0 - io command block ; A3 - io command block ; D0 - IO error ; D4 - scrapInfo ; D5 - scrapHandle ; D6 - scrapState ; CC's - set according to Open or create result (e.g. IO error) ; ;-----------------------------------Scrap----------------------------------- ; StdEntry MOVE.L (SP)+,A1 ; save local return address LINK A6,#stdLink ; set up frame MOVEM.L D2-D7/A2-A4,-(SP) ; save the regs MOVE.L A1,-(SP) ; push back on return MOVEM.L scrapVars,D4/D5/D6/A2 ; preload scrapInfo,handle,state and name LEA scrapHandle,A4 ; convenient pointer LEA scrapIO(A6),A0 ; set up io command block MOVE.L A0,A3 ; Save I/O ptr in A3 MOVE.L A2,IOFileName(A0) ; set file name ptr CLR.W IODrvNum(A0) ; use default drive CLR.W IOFileType(A0) ; clear type, permissions CLR.L IOOwnBuf(A0) ; use system buffer TST D6 ; scrapState = disk BNE.S goHome0 ; skip open if not on disk ; Now try to open; if that fails, create and open the file StdOpen _Open ; try an open first BEQ.S goHome ; and escape if good CMP #OpWrErr,D0 ; if open already, pretend it's ok BEQ.S goHome0 CMP #FNFErr,D0 ; create if not there BNE.S goHome _Create ; io cmd set up BNE.S goHome BRA StdOpen ; go open now ;-----------------------------------Scrap----------------------------------- ; ; FUNCTION UnloadScrap: LONGINT; ; FUNCTION LoadScrap: LONGINT; ; ; Reminder: ; D4 = scrapLength from StdEntry ; D5 = scrapHandle ; D6 = scrapState ; A4^ scrapHandle ; ;-----------------------------------Scrap----------------------------------- ; UnloadScrap BSR StdEntry ; go set up local world BNE.S err0Exit ; escape if IO error TST D6 ; escape if on disk or un-inited BLE.S ok0Exit ; scrapState is <=0' BSR StdOpen ; go open it MOVE.L D4,D0 ; pass the length BSR.S SetupRW ; set up IO cmd _Write ; write it out BNE.S err0Exit MOVE.L D5,A0 ; get rid of the handle _DisposHandle ; ignore errors from dispose CLR.L (A4)+ ; indicate on disk(scrapHandle) CLR.L (A4)+ ; indicate on disk(scrapState) ok0Exit MOVEQ #0,D0 ; no error err0Exit EXT.L D0 MOVE.L D0,8(A6) ; return result code (link+0 param) MOVEQ #0,D0 ; see you later StdExit MOVEM.L (SP)+,D2-D7/A2-A4 ; see you later StdUNLK UNLK A6 stdRTS MOVE.L (SP)+,A0 ADD D0,SP JMP (A0) goHome0 MOVEQ #0,D0 ; jam no error goHome RTS ; return LoadScrap BSR StdEntry ; go set up the world BNE err0Exit TST D6 ; check scrap state BNE.S ok0Exit ; escape if in memory MOVE.L D4,D0 ; get scrap length _NewHandle BNE err0Exit MOVE.L A0,(A4)+ ; save the new handle(scrapHandle) ADDQ.L #1,(A4)+ ; 0 disk => 1 memory(scrapState) BSR.S SetupRW2 ; set up IO cmd for read ;jwp MOVE.L D4,IOByteCount(A0) ; set up the real byte count ;jwp _Read ; read it in BRA err0Exit ;-----------------------------------Scrap----------------------------------- ; ; Set up Read/Write for IO in command block off A6 ; Absolute pos mode at beginning ; ; Entry: ; A0 - (SetupRW2) handle for scrap ; A3 - io cmd block ; D0 - length to read or write ; D5 - scrap handle from stdEntry ; Exit: ; A0 - iocommand block ; ;-----------------------------------Scrap----------------------------------- SetupRW MOVE.L D5,A0 ; set up buffer address SetupRW2 MOVE.L (A0),IOBuffer(A3) ; to scrap handle MOVE.L D0,IOByteCount(A3) ; set up the buffer count MOVE #1,IOPosMode(A3) ; absolute position CLR.L IOPosOffset(A3) ; position to beginning MOVE.L A3,A0 ; set up for I/O RTS ; return for read or write ;-----------------------------------Scrap----------------------------------- ; ; FUNCTION ZeroScrap: LONGINT; ; ; Reminder: ; D4 = scrapLength from StdEntry ; D5 = scrapHandle ; D6 = scrapState ; ;-----------------------------------Scrap----------------------------------- ; ZeroScrap BSR StdEntry ; D0 set to 0 by above BNE err0Exit MOVE.L D0,scrapInfo ; zero out info ADDQ #8,4(A4) ; increment validation word TST D6 BEQ.S zeroDisk ; see if on disk BGT.S zeroMem ; see if in memory ; allocate a new scrap _NewHandle ; create the handle if the location BRA.S zsExit ; was negative zeroMem MOVE.L D5,A0 ; get the existing handle _SetHandleSize zsExit MOVE.L A0,(A4)+ ; save the handle(scrapHandle) MOVE (A4)+,(A4) ; positive => 1 memory(scrapState) BRA err0Exit zeroDisk CLR.L IOLEOF(A0) ; set to zero _SetEOF BRA err0Exit ;-----------------------------------Scrap----------------------------------- ; ; FUNCTION GetScrap( hDest: Handle; what: ResType; ; VAR offset: LONGINT ): LONGINT; ; ; Reminder: ; D4 = scrapLength from StdEntry ; D5 = scrapHandle ; D6 = scrapState ; ;-----------------------------------Scrap----------------------------------- ; gsOffset .EQU 8 ; VAR offset gsType .EQU gsOffset+4 ; type gsHDest .EQU gsType+4 ; destination handle gsResult .EQU gsHDest+4 ; result longint ; Utility to "get" bytes from the scrap on disk or in memeory ; ; Entry: ; D3 contains byte offset in scrap ; D0 contains amount to read ; A1 points to receiving buffer DoGet TST D6 ; see if on disk BEQ.S getDisk ; Get the data from the scrap handle in memeory MOVE.L D5,A2 ; get scrapHandle MOVE.L (A2),A0 ; set up source for move ADD.L D3,A0 ; add in offset _BlockMove BRA goHome0 ; return zero ; Get the data from the file getDisk BSR SetupRW ; fill out I/O command blk MOVE.L D3,IOPosOffset(A0) ; absolute read @ D3 MOVE.L A1,IOBuffer(A0) ; point to dest buffer _Read RTS GetScrap BSR StdEntry ; Open things up BNE.S err12Exit ; escape if file error ; Make sure scrap exists MOVEQ #noScrapErr,D0 ; scrap don't exist(nor does grammar) TST D6 ; check scrap state BMI.S err12Exit ; escape if not zeroed ; Start looking through the scrap ; ; D0 is used for read lengths ; D3 is the offset @ which to read ; A1 points to dest buffer MOVEQ #0,D3 ; start offset readNext CMP.L D4,D3 ; see if done with list BGE.S notFound MOVEQ #scrData,D0 ; read object header(8) LEA dType(A6),A1 ; buffer to place stuff BSR.S DoGet ; go get it BNE.S err12Exit okRead ADDQ.L #scrData,D3 ; point to next entry(more below) MOVE.L (A1)+,D7 ; get type from file CMP.L gsType(A6),D7 ; and compare BEQ.S foundIt ADD.L (A1)+,D3 ; by adding 8 plus length ADDQ.L #1,D3 ; round up to even BCLR D0,D3 ; assume D0 = 0 BRA readNext ; We now have D3 offset to correct entry, A1 points to object's length ; If the dest handle is nil, escape after passing back offset and D0 ; contains the length notFound MOVEQ #noTypeErr,D0 ; couldn't find type BRA.S err12LExit ; We now have D3 offset to correct entry, A1 points to object's length ; If the dest handle is nil, escape after passing back offset and D0 ; contains the length foundIt MOVE.L gsOffset(A6),A2 ; set up var address MOVE.L D3,(A2) ; return the offset to caller MOVE.L (A1),D0 ; Get object's length for return in D0 MOVE.L D0,20(A6) ; and return length for now MOVE.L gsHDest(A6),D1 ; set up destination BEQ.S go12Exit ; return length if no handle MOVE.L D1,A0 ; set it's size _SetHandleSize BNE.S err12Exit ; Do the actual fetch of the object MOVE.L (A1),D0 ; and read it's length MOVE.L (A0),A1 ; and read into dereferenced handle BSR.S DoGet BEQ.S go12Exit ; if no error(the length is stuffed above) err12Exit ; see you later EXT.L D0 ; turn OS error into a long err12LExit MOVE.L D0,20(A6) ; and return error code go12Exit ; link(8) + params(12) MOVEQ #12,D0 BRA StdExit ;-----------------------------------Scrap----------------------------------- ; ; FUNCTION PutScrap( length: LONGINT; what: ResType; pSource: Ptr ): LONGINT; ; ; Doesn't check for existing object of that type because caller ; will have always zeroed scrap prior to this. ; ; Reminder: ; D4 = scrapLength from StdEntry ; D5 = scrapHandle ; D6 = scrapState ; ;-----------------------------------Scrap----------------------------------- ; psSource .EQU 8 ; source ptr psType .EQU psSource+4 ; type psLength .EQU psType+4 ; source length psResult .EQU psLength+4 ; result PutScrap BSR StdEntry ; set up frame BSR SetupRW ; and ready for a write MOVEQ #noScrapErr,D0 ; assume the worst TST D6 ; see if on disk BMI.S err12Exit MOVEQ #scrData,D0 ; length of type LEA psType(A6),A0 ; save type and length BSR.S DoPut ; ignore error, catch it below MOVE.L psSource(A6),A0 ; get source ptr MOVE.L psLength(A6),D0 ; save the length's worth MOVEQ #-2,D1 ; evenizer mask ADDQ.L #1,D0 ; round up to even AND.L D1,D0 BSR.S DoPut ; errors handled on exit MOVE.L D4,-(A4) ; and save new scrap length(ScrapInfo) BRA.S err12Exit ; see you later D0 set from above DoPut MOVE.L D4,IOPosOffset(A3) ; set file position to old size ADD.L D0,D4 ; add this length to get new size TST D6 ; see if on disk BEQ.S putDisk MOVE.L D5,A1 ; get scrap handle _PtrAndHand ; add on to handle RTS putDisk MOVE.L A0,IOBuffer(A3) ; stuff ptr to data MOVE.L D0,IOByteCount(A3) ; 8 bytes of I/O MOVE.L A3,A0 ; restore I/O command _Write RTS .END }x;File SegLoader.Text ; MACWORKS copy ;--------------------------------------------------- ; ; Segment Loader for MacIntosh Operating System ; ; written by Andy Hertzfeld 09-May-83 ; ; ; Here is the new resource-based segment loader. It ; is capable of loading multiple Lisa-style code segments ; using a jump table scheme similar to the Lisa "physical ; executable" format. ; ; The loader is also the part of the system that cuts back ; the application heap and builds an "A5 world" for the ; application. ; ; The loader will preserve the handle in low memory called ; "theScrap" across world swaps. ; ; Modification History: ; ; 29-May-83 AJH Changed jumptable from 10 bytes/entry to 8 bytes/entry ; 01-Jun-83 AJH preserved theScrap; added page two options ; 02-Jun-83 AJH fixed bug in ExitToShell to push page 2 word ; 04-Jun-83 AJH made Launch clear D7 & 20(A5) for stupid Lisa Pascal ; 08-Jun-83 AJH increased size of appName; made it use AppParmHandle ; 11-Jun-83 AJH cleaned up BadOpen error exit stuff ; 16-Jun-83 AJH made it InitApplZone early so it only opens once ; 16-Jun-83 AJH made it compact before locking code segments ; 17-Jun-83 AJH fixed bug (no InitApplZone) introduced yesterday ; 06-Aug-83 BLH Added initialization of DragHook, DeskHook, CloseOrnHook, ; restProc, saveProc, saveSP, taskLock, fScaleDisable, ; resErrHook right after InitApplZone. These all used to ; be in InitWindows (except fScaleDisable). ; 08-Aug-83 AJH removed compact before locking (now rMgr does it!) ; 09-Aug-83 SC Fixed bug in scrap stuff(D0 lost through NewHandle) ; 10-Aug-83 AJH moved LoadTrap to LoadSeg; loader calls SetApplLimit ; 11-Aug-83 AJH made it preserve scrap by moving it to stack ; 12-Aug-83 AJH moved globals to SysEqu; use deepShit alert in SysErr ; made ExitToShell use a low memory pBlock ; save parameters in lomem earlier ; 13-Aug-83 SC Dropped flushevents ; 16-Aug-83 AJH Compute screen sound address relative to memTop (instead of ; ScreenBase) ; 18-Aug-83 SC Changed theScrap to scrapHandle and changed BEQ to BLE ; 19-Aug-83 LAK Now inits StkLowPt. ; 06-Sep-83 AJH BadOpen now deep shits ; 10-Sep-83 AJH Fixed bug -- it wasn't releasing segment 0! ; 25-Sep-84 KWK If no Current Application, still does Goodbye kiss loop ; ;-------------------------------------------------------- ; .INCLUDE TlAsm-SYSEQU.TEXT .INCLUDE TlAsm-SYSMACS.TEXT .INCLUDE TlAsm-GRAFEQU.TEXT .INCLUDE TlAsm-GRAFTYPES.TEXT .INCLUDE TlAsm-TOOLEQU.TEXT .INCLUDE TlAsm-ResEqu.Text .INCLUDE TlAsm-QuickMacs.TEXT .INCLUDE TlAsm-ToolMacs.TEXT .INCLUDE TlAsm-SysErr.TEXT .PROC Loader,0 .DEF Launch,Chain,ExitToShell .DEF InstallRDrivers .DEF LoadSeg,UnloadSeg .DEF GetAppParms .REF MakeStkPB ; segment header definitions SegJTOffset .EQU 0 ; offset of 1st jumpTable entry SegJTEntries .EQU 2 ; number of jumpTable entries SegHdrSize .EQU 4 ; the header is four bytes long ; misc definitions SegLoadTrap .EQU $A9F0 ; LoadSeg trap ID ;------------------------------------------------------------------------------ ; ; PROCEDURE LoadSeg(segID: INTEGER); ; ; LoadSeg is used to load a segment and patch all the jump table entries for ; that segment. It is usually called from the jump table entry and almost ; never called directly by the application. It then transfers control ; to the newly loaded code. ; ; All registers are preserved until the newly loaded code is launched. ; If the segment can't be found, a deep shit alert is posted. ; ;------------------------------------------------------------------------------ LoadSeg MOVEM.L D0-D2/A0-A1,-(SP) ;all registers must be preserved MOVE.W 24(SP),D0 ;get the segment ID BSR.S LoadCode ;ask resources to load the segment BEQ.S SegError ;if not, give up BSET #7,(A0) ;lock it down MOVE.L (A0),-(SP) ;handle -> pointer CLR.B (SP) ;clear the high byte MOVE.L (SP)+,A0 ;get the pointer MOVE.L A5,A1 ;copy world base address ADD.W CurJTOffset,A1 ;offset by the current offset ADD.W SegJTOffset(A0),A1 ;compute address of 1st entry CMP.W #$4EF9,4(A1) ;is it already loaded? BEQ.S GoLaunch ;if so, don't bother to load ; we must patch the jump table to point to the newly loaded segment. At this ; point A1 points to the first jump table entry. MOVE.W SegJTEntries(A0),D0 ;get the number of entries BEQ.S GoLaunch ;if none, just go launch it MOVE.W 24(SP),D1 ;get the segment ID MOVEQ #0,D2 ;clear out high part of D2 PatchJTLoop MOVE.W (A1)+,D2 ;pick up the offset MOVE.W D1,-2(A1) ;remember the segment ID in entry MOVE.W #$4EF9,(A1)+ ;patch in the "JMP.L" opcode PEA SegHdrSize(A0,D2.L) ;compute the entry point address MOVE.L (SP)+,(A1)+ ;move in the entry point address SUBQ #1,D0 ;more entries to do? BNE.S PatchJTLoop ;loop till done ; now we can transfer control to the newly loaded code at the proper entry point GoLaunch MOVE.L 20(SP),A1 ;get the return address from the trap SUBQ.L #6,A1 ;back up to the JMP.L opcode MOVE.L A1,22(SP) ;patch the return address MOVEM.L (SP)+,D0-D2/A0-A1 ;restore the registers ADDQ #2,SP ;strip parameter TST.B LoadTrap ;debugging on? BEQ.S @1 ;go launch if its not .WORD $A9FF ;invoke debugger @1 RTS ;launch the code! ; here is the error handler for when we couldnt load a segment we need. Its ; a deep shit alert. SegError MOVEQ #DSLoadErr,D0 ;get deep shit ID _SysError ;invoke deep shit - dont come back .WORD $A9FF ;trap to debugger, just in case ; LoadCode is a code saving utility that loads the segment with the resource ID ; specified in D0. It returns the segment handle in A0 LoadCode SUBQ #4,SP ;make room for function result MOVE.L #CodeRType,-(SP) ;push "CODE" MOVE.W D0,-(SP) ;push the segment ID _GetResource ;load it MOVE.L (SP)+,A0 ;get result in A0 MOVE.L A0,D0 ;better set Z-flag based on result RTS ;return to caller ;------------------------------------------------------------------------------ ; ; PROCEDURE UnloadSeg(routineAddr: Ptr); ; ; UnLoadSeg is used to unload a segment when the application feels its no ; longer needed for a while. It patches all of the segment's jump table ; entries back to the "load me" state. The parameter is the address of any ; routine within the segment. ; ;------------------------------------------------------------------------------ UnloadSeg MOVE.L 4(SP),A0 ;get the address of the routine CMP.W #$4EF9,(A0) ;is it already unloaded? BNE.S DoneUnload ;if so, we're done ; the first thing we must do is figure out the handle of the segment MOVE.W -2(A0),D0 ;get the segment ID BSR.S LoadCode ;get the segment handle BCLR #7,(A0) ;unlock it MOVE.L (A0),A0 ;handle -> pointer MOVE.L A5,A1 ;copy world base address ADD.W CurJTOffset,A1 ;offset by current offset ADD.W SegJTOffset(A0),A1 ;compute address of 1st entry MOVE.W SegJTEntries(A0),D0 ;get the number of entries BEQ.S DoneUnload ;if zero, we're all done ; loop through each jump table entry, patching it back to the "load me" state UnpatchLoop MOVE.W (A1),D1 ;remember the segment ID MOVE.L 4(A1),D2 ;get the current address SUB.L A0,D2 ;subtract the segment base address SUBQ.L #SegHdrSize,D2 ;subtract the header size MOVE.W D2,(A1)+ ;move in the offset MOVE.W #$3F3C,(A1)+ ;move in the "push immediate" opcode MOVE.W D1,(A1)+ ;move in the segment ID MOVE.W #SegLoadTrap,(A1)+ ;move in the "SegLoad" trap SUBQ #1,D0 ;more to do? BNE.S UnpatchLoop ;loop until done ; we're all done with unloading the segment so strip the parameter and ; return to the caller DoneUnload MOVE.L (SP)+,(SP) ;strip the parameter RTS ;return to caller ;------------------------------------------------------------------------------ ; ; PROCEDUREs Launch, Chain, ExitToShell: ; ; Here is the main part of the segment loader that actually launches ; an application. It opens the resource file specified by the input name, ; loads segment 0 to get the jumptable and global size information, optionally ; cuts back the application heap and kicks off the application by invoking ; its first jump table entry. ; ; ; Warning -- LAUNCH obliterates the application heap so if an error occurs ; (like the file isn't executable) the code that called us is no longer ; "in the zone". Callers of LAUNCH should be very careful...(they probably ; should use a deep shit alert to put up a message and then re-launch themselves) ; ;------------------------------------------------------------------------------ ; This part of the code is here so it can be accessible by short branches. ; Compute the address of sound page 2 and go modify the stackBase if ; neccessary. SoundPage2 MOVE.L MemTop,D0 ;get address of top of RAM SUB.L #$00005F00,D0 ;compute address of sound page 2 BRA SetNewStack ;modify stackBase if necessary ; First we have some an alternate entry point "Chain" which is just like ; launch except it doesn't cut back the heap. Chain CLR.W LaunchFlag ;flag not to cut back heap BRA.S LaunchCom ;fall into common code ; Here is the main entry point for launch Launch ST LaunchFlag ;flag that we should cut back the heap LaunchCom MOVE.W 4(A0),CurPageOption ;remember page 2 options word MOVE.L (A0)+,A0 ;save name ptr LEA CurApName,A1 ;get address to stuff the name MOVEQ #32,D0 ;move 32 bytes worth _BlockMove ;move it in ; first close any previously open application, if any MOVE CurApRefNum,D0 ;get refnum of current application BLE.S SkipClose ;if none, skip the close MOVE.W D0,-(SP) ;push the refNum _CloseResFile ;close it CLR.W CurApRefNum ;flag that no application is open ; kwk -- moved skipclose above loop for goodbye kiss checking, thus always checks, ; even if no current application (normal state if not in Finder). ;jwp ; at this point, the loader is about to dismantle the applications heap zone. ; loop through the unit table, making a farewell call to any driver that wants ; one (before we obliterate the application zone) SkipClose MOVEM.L D0-D1/A0-A1,-(SP) ;save registers SUB #IOQElSize,SP ;allocate pBlock MOVE #-1,CSCode(SP) ;set up control code MOVE.L UTableBase,A1 ;point to unit table MOVE.W UnitNtryCnt,D1 ;get # of entries in unit table GoodByeLoop MOVE.L (A1)+,D0 ;get the DCE handle BEQ.S NextGoodBye ;if NIL, none installed MOVE.L D0,A0 MOVE.L (A0),A0 ;get DCE ptr BTST #DNeedGoodbye,DCtlFlags(A0) ;need a goodbye kiss? BEQ.S NextGoodBye ;if not,skip ; we found one that wants a goodBye call so issue the control call MOVE.W DCtlRefNum(A0),IORefNum(SP) ;set up the refNum MOVE.L SP,A0 ;point to the DCE _Control ;kiss it goodbye... NextGoodBye SUBQ #1,D1 ;more to do? BNE.S GoodByeLoop ;if so, loop ADD #IOQElSize,SP ;deallocate pBlock MOVEM.L (SP)+,D0-D1/A0-A1 ;restore registers ;jwp ; now initialize the application heapZone, if we're launching MOVE.L BufPtr,SP ;start stack under screen/debugger CLR.L StkLowPt ;keep VBL task out TST.W LaunchFlag ;is it a launch? BEQ.S OpenApp ;if not, skip ; before obliterating the heap, save the scrap on the stack MOVE.L scrapHandle,D0 ;get the scrap handle BLE.S GoInitAZone ;if none, skip MOVE.L D0,A0 ;get the handle _GetHandleSize ;get its size ;jwp - make sure that the scrap handle is never an odd size ADDQ.L #1,D0 ;round up to nearest even number BCLR #0,D0 ;jwp SUB.L D0,SP ;allocate space for it MOVE.L SP,A1 ;set up destination for move MOVE.L (A0),A0 ;set up source for move MOVE.L D0,-(SP) ;remember the size _BlockMove ;move it! ; re-init the application heap zone, destroying the world... GoInitAZone _InitApplZone ;cut back the heap CLR.W CurApRefNum ;InitApplZone closes resource files ;allocate a new handle for the scrap to be copied into, if necessary. TST.L scrapHandle ;did we have a scrap? BLE.S SkipScrap ;if none, skip ; we had a scrap so better allocate a new handle for it and rescue its contents ; from the stack MOVE.L (SP)+,D1 ;get the size of the scrap MOVE.L D1,D0 ;set up size for NewHandle _NewHandle ;allocate a handle for it MOVE.L A0,scrapHandle ;remember the handle MOVE.L D1,D0 ;get size for blockMove MOVE.L (A0),A1 ;get destination pointer MOVE.L SP,A0 ;get source pointer _BlockMove ;move it in! ADD.L D1,SP ;deallocate scrap save buffer SkipScrap _RDrvrInstall ;fix up ram based drivers ; now that the heaps in good shape, open the new application file after reiniting ; some important hooks and globals OpenApp CLR.L DragHook ;No drag hook yet CLR.L DeskHook ;No desk hook for hit-testing desk. LEA CloseOrnHook, A0 ; Point to closeOrnHook CLR.L (A0)+ ;clear closeOrnHook CLR.L (A0)+ ;clear RestProc CLR.L (A0)+ ;clear saveProc CLR.W TaskLock ;clear taskLock, fScaleDisable. CLR.L ResErrProc ;and resource error proc. ; open the application resFile (which will pre-load some resources) SUBQ #2,SP ;make room for function result PEA CurApName ;push file name ptr _OpenResFile ;open it MOVE.W (SP)+,CurApRefNum ;remember it in low memory BLE BadOpen ;branch if open wasn't successful ; now load in segment 0, which has the A5 world information as well as the ; jump table MOVEQ #0,D0 ;get ID for segment 0 BSR LoadCode ;load it in =>seg handle in A0 BEQ BadOpen ;if we failed, report error MOVE.L A0,SaveSegHandle ;remember code 0 handle in loMem ; set up A5 and A7 for this application MOVE.L (A0),A0 ;point to seg 0 info ; adjust the stack base according to the page 2 options word TST.W CurPageOptions ;are any page 2 options requested? BEQ.S SetA5 ;if not, go build A5 world BPL.S SoundPage2 ;if so, go handle sound page 2 MOVE.L MemTop,D0 ;start at memTop SUB.L #$0000D900,D0 ;compute video page 2 address SetNewStack CMP.L SP,D0 ;should we move down the stack BGE.S SetA5 ;if not, skip MOVE.L D0,SP ;move it down SetA5 SUB.L (A0)+,SP ;allocate "above A5" space MOVE.L SP,A5 ;set up A5 SUB.L (A0)+,SP ;allocate "below A5" space MOVE.L A5,CurrentA5 ;remember A5 for this application MOVE.L SP,CurStackBase ;remember stack for this one, too MOVE.L SP,StkLowPt ;for heap-stack crashes ; move in the jump table to where it belongs MOVE.L (A0)+,D0 ;get the jump table size MOVE.L (A0)+,A1 ;get the load offset MOVE.W A1,CurJTOffset ;remember the offset ADD.L A5,A1 ;add in the base address LEA 2(A1),A3 ;remember the launch address _BlockMove ;move it in ; now that things are set up, we can release segment 0 MOVE.L SaveSegHandle,-(SP) ;push the segment 0 handle _ReleaseResource ;de-allocate it ; set up the parameters to the application LEA 8(A5),A0 ;point to parameter area CLR.L (A0)+ ;standard input CLR.L (A0)+ ;standard output MOVE.L AppParmHandle,(A0)+ ;parameter pointer CLR.W (A0)+ ;physExec flag for stupid Lisa Pascal ; set the default application heap zone limit based on the current stack MOVE.L SP,A0 ;get the stack SUB.L DefltStack,A0 ;subtract buffer zone _SetApplLimit ;set the new limit ; OK, we can actually kick off the application now. MOVEQ #0,D7 ;clear D7 for stupid Pascal JSR (A3) ;launch the application ; If we reached this point, the application must have successfully terminated. ; Close its resource file and chain back to the finder. ExitToShell MOVE.W CurApRefNum,-(SP) ;push the app's refnum _CloseResFile CLR.W CurApRefNum ;jwp SUB.L A0,A0 ; clear out A0 _SetGrowZone ; disable application's growZone handler SUBQ #4,SP ; load the scrap into memory _LodeScrap ADDQ #4,SP ; trashes pascal regs JSR MakeStkPB MOVE.W BootDrive,IOVRefNum(A0) ; prefix to 'boot' drive _SetVol ADD #IOVQElSize,SP ; clean up stack ;jwp LEA LoaderPBlock,A0 ;point to lomem param block MOVE.L A0,A1 ;copy to A1 PEA FinderName ;get finder name pointer MOVE.L (SP)+,(A1)+ ;put finder name ptr in pBlock CLR.L (A1)+ ;no page 2 usage BRA Launch ;launch it! ; here is the error handler for when we can't open the file. We've already ; obliterated the world (possibly) so just deep shit BadOpen MOVEQ #DSBadLaunch,D0 _SysError ;post the error .WORD $A9FF ;invoke debugger ;------------------------------------------------------------------------------ ; ; PROCEDURE GetAppParms(VAR apName: Str255; ; VAR apRefNum: INTEGER; ; VAR apParam: Ptr) ; ; GetAppParms is a utility routine that returns some information about the ; currently executing application. It returns its name (the first 24 ; characters, anyway), its resource refNum and a pointer to the parameter ; block passed by the finder. ; ;------------------------------------------------------------------------------ GetAppParms MOVE.L (SP)+,A0 ;pull off the return address MOVE.L (SP)+,A1 ;get pointer to apParam MOVE.L 16(A5),(A1) ;return a pointer to finder pBlock MOVE.L (SP)+,A1 ;get pointer to apRefNum MOVE.W CurApRefNum,(A1) ;pass back the refNum MOVE.L (SP)+,A1 ;point to place to stuff name string MOVE.L A0,-(SP) ;replace return address LEA CurApName,A0 ;point to name in low memory MOVEQ #32,D0 ;move 32 bytes _BlockMove ;move it! RTS ;return to caller (params already stripped) ;------------------------------------------------------------------------------ ; ; InstallRDrivers fixes up the unit table after the application heap ; is obliterated between applications. ; ;------------------------------------------------------------------------------ InstallRDrivers MOVEM.L D0-D4/A0-A3,-(SP) ; loop through the unit table, checking for drivers in the application heap MOVE.L UTableBase,A3 ; get pointer to unit table MOVE.W UnitNtryCnt,D3 ; get # of entries in unit table MOVEQ #-1,D4 ; the first unit is refNum -1 IRDLoop MOVE.L (A3)+,D0 ; get the DCE handle BEQ.S NextIRD ; if NIL, skip MOVE.L D0,A1 ; get handle in A-reg MOVE.L (A1),A1 ; get DCE ptr BTST #DRamBased,DCtlFlags+1(A1) ;is it ROM-based? BEQ.S NextIRD ; if so, skip MOVE.L DCtlDriver(A1),D0 ; get driver handle BEQ.S NextIRD ; if none, skip CMP.L ApplZone,D0 ; which zone is it in? BLT.S DoSysZDriver ; special case ones in the system zone ; we got a driver in the application heap, so re-init its DCE MOVEQ #DCtlEntrySize-1,D0 ; get size in bytes MOVE.L A1,A0 ; point to DCE start @1 CLR.B (A0)+ ; clear a byte DBRA D0,@1 ; loop till cleared ; flag it as RAM-based and set up the refNum BSET #DRamBased,DCtlFlags+1(A1) MOVE.W D4,DCtlRefNum(A1) ; set up the refNum (queue inited to 0s) ; inspect the next table entry NextIRD SUBQ #1,D4 ;decrement refNum SUBQ #1,D3 ;more to do? BNE.S IRDLoop ;loop until done MOVEM.L (SP)+,D0-D4/A0-A3 RTS ; all done! ; handle drivers on the system zone by zero their window or storage ; if its in the application zone DoSysZDriver CLR.L DCtlWindow(A1) ; zero its window MOVE.L DCtlStorage(A1),D0 ; get its storage handle CMP.L ApplZone,D0 ; is it in the system zone? BLT.S NextIRD ; if so, its cool CLR.L DCtlStorage(A1) ; clear it cause its invalid BRA.S NextIRD ; go do the next one .END $EXEC{setprefix.text, sets the prefix to be Arg0} F{iler}P{refix}%0{prefix 1} {no change to prefix 2} {no change to prefix 3} {don't set for boot} Q{uit the filer} $ENDEXEC }; FILE Sony.text ; MACWORKS original ;_______________________________________________________________________ ; ; ; Lisa/Mac Sony Disk Driver ; ; written by Jeff Parrish 23-Oct-83 ; ; 19-Jun-84 KWK Fixed DiskPrime/DiskDone to position for read/write ; and update correctly. ; 02-Jul-84 KWK/RDC Really fixed DiskPrime (ChkDrvNum changes A1!) ;_______________________________________________________________________ .NOLIST .INCLUDE Tlasm-SysEqu.Text .INCLUDE Tlasm-SysErr.Text .INCLUDE Tlasm-SysMacs.Text .INCLUDE Tlasm-SonyEqu.Text .LIST .PROC DiskDrvr,0 .REF InitQueue,EnQueue,JmpTblInit .DEF AddDrive ; ; Here is the driver format header ; SonyDrvr .WORD $4F00 ; read, write, control, status, needs lock .WORD 0,0 ; no delay or EMask .WORD 0 ; no menu ; Entry point offset table .WORD DiskOpen-DiskDrvr ; open .WORD DiskPrime-DiskDrvr ; prime .WORD DiskControl-DiskDrvr ; control -- eject is call 1 .WORD DiskStatus-DiskDrvr ; status -- call 1 for info .WORD DiskClose-DiskDrvr ; close -- just RTS (NOT CLOSABLE) .BYTE 5 .ASCII '.Sony' ;------------------------------------------------------------------------- ; ; Routine: DiskOpen ; ; Arguments: A1 (input) -- pointer to DCE ; A0 (input) -- pointer to control call parameter block: ; D0 (output) -- result code ; ;------------------------------------------------------------------------- DiskOpen MOVEQ #,D0 ; get memory for driver variables ADD.L D0,D0 _NewPtr ,SYS,CLEAR MOVE.L A0,SonyVars ; and keep pointer in low memory MOVE.L A0,A2 ; save for later MOVE.L A1,(A0) ; save DCE pointer MOVE.B #$80,DCtlQueue+1(A1); set up driver version byte MOVE.W DCtlRefNum(A1),D2 ; this driver LEA DrvQHdr,A1 ; initialize the drive queue, too JSR InitQueue MOVEQ #Drv1,D0 ; init drive 1 CLR.B WriteProt(A2,D0) ; start out not write protected CLR.B DiskInPlace(A2,D0) ; and no disk inplace MOVE.B #$1,Installed(A2,D0); and drive is installed CLR.B Sides(A2,D0) ; and 1 sided LEA DQEL(A2,D0),A0 ; first drive queue element MOVEQ #1,D0 BSR.S ToAddDrive MOVE.W #800,DQDrvSize(A0) ; block size for sonys - format package ADD.W #DrvLclLth,A0 ; init drive 2 CLR.B WriteProt(A0) ; start out not write protected CLR.B DiskInPlace(A0) ; and no disk inplace MOVE.B #$1,Installed(A0) ; and drive is installed TST.B $624 ; is there really an external drive? BNE.S @1 ST Installed(A0) ; no @1 CLR.B Sides(A0) ; and 1 sided MOVEQ #2,D0 BSR.S ToAddDrive MOVE.W #800,DQDrvSize(A0) ; block size for sonys - format package MOVEQ #0,D0 ; return no error from DiskOpen RTS ;------------------------------------------------------------------------- ; ; Routine: DiskClose ; ; Arguments: A1 (input) -- pointer to DCE ; A0 (input) -- pointer to control call parameter block: ; D0 (output) -- result code ; ;------------------------------------------------------------------------- DiskClose MOVEQ #0,D0 ; no errors RTS ;------------------------------------------------------------------------- ; ; Routine: AddDrive ; ; Arguments: A0 (input) -- pointer to block of mem for queue. ; D0 (input) -- high word = drive # ; low word = driver refnum ; A1 (output) -- pointer to drive queue header. ; ;------------------------------------------------------------------------- ToAddDrive SWAP D0 MOVE.W D2,D0 AddDrive MOVE.L D0,DQDrive(A0) ; drive number and driver refnum LEA DrvQHdr,A1 ; put into the drive queue JMP Enqueue ;------------------------------------------------------------------------- ; ; Routine: DiskDone ; ; Arguments: D0 (input) -- last error ; A1 (output) -- pointer to disk DCE ; ;------------------------------------------------------------------------- DiskDone MOVE.W D0,DskErr ; save last error for file system MOVE.L sonyVars,A1 ; get pointer to locals CLR.B active(A1) ; reset disk active MOVE.L DiskUnitPtr(A1),A1 ; and pointer to disk DCE MOVE.L JIODone,-(SP) RTS ; use IODone vector ;------------------------------------------------------------------------- ; ; Routine: DiskControl ; ; Arguments: A0 (input) -- pointer to control call parameter block: ; CSCode = 1 for KillIO ; 5 for Verify ; 6 for Format ; 7 for Eject ; 8 for setting tag buffer ; A1 (input) -- pointer to disk DCE ; D1 (?????) -- ; D0 (output) -- result code ; ;------------------------------------------------------------------------- DiskControl MOVEM.L D6/A0-A1,-(SP) MOVE.W CSCode(A0),D6 SUBI.W #2,D6 ; change 5,6,7,8 to 3,4,5,6 for sony cntlr CMPI.W #6,D6 ; is it a good command? BGT.S DiskDone ; no CMPI.W #3,D6 ; is it still a good command? BMI.S DiskDone ; no BSR CkDrvNum ; check for valid drive number BNE Done ; exit if bad drive error CMPI.W #6,D6 ; should we set up a new tag buffer? BNE.S @1 MOVE.L CSParam(A0),TagBufPtr(A1) ; set or clear ptr to separate buffer CLR.W D0 ; no errors. BRA.S Done ; always a good exit @1 MOVE.W IOVDrvNum(A0),D4 ; which drive MOVE.L SonyStart,A3 ; get start of disk 1 routines MOVEM.L D1-D6,-(SP) ; save our registers JSR (A3) ; call UnitIO to access the disk MOVEM.L (SP)+,D1-D6 ; replace our registers BEQ.S @2 ; no errors? NEG.W D0 ; make sure all errors are negative CMPI.W #-$15,D0 ; unable to verify a track? BNE.S @2 MOVE.W #DataVerErr,D0 ; bad verify @2 CMPI.W #5,D6 ; was it an eject command? BNE.S Done ; no - then skip the DIP stuff MOVE.L sonyVars,A1 ; get location of twiggy locals MOVE.W #Drv1,D6 ; assume drive 1 CMPI.B #2,D4 ; drive 1 or 2? D0=1,2 for drive 1,2 BMI @3 MOVE.W #Drv2,D6 ; offset to drive 2's locals @3 MOVE.B #0,DiskInPlace(A1,D6); save the disk state Done MOVEM.L (SP)+,D6/A0-A1 BRA DiskDone ;------------------------------------------------------------------------- ; ; Routine: DiskStatus ; Arguments: A0 (input) -- pointer to status call parameter block: ; CSCode = 8 for drive status ; CSParam: ; (0) current track location ; (2) bit7=1=write-protected ; (3) $FC-$FF= just ejected, ; 0=no DIP, 1=DIP, 2=clamped ; (4) 0=don't know, 1=inst., $FF=not inst. ; (5) bit7=0=1 sided ; (6) drive queue element ; (18) $FF for 2-sided format this diskette ; (19) $FF if diskprime called ; (20) soft error count (word) ; ; ; Function: The status call returns current status for the drive requested. ;------------------------------------------------------------------------- DiskStatus MOVEM.L D4/D6/A1/A3,-(SP) MOVEQ #StatusErr,D0 ; assume status error CMP.W #DrvStsCode,CSCode(A0) ; drive status call? BNE.S DiskDone ; exit for other calls BSR.S CkDrvNum BNE.S DiskDone ; ; check if the disk is write protected first - then pass back all info ; ADD.W D1,A1 ; sonyVars+driverOffset CLR.B WriteProt(A1) ; assume the disk is not write-protected MOVE.W IOVDrvNum(A0),D4 ; which drive MOVE.W #6,D6 ; check for write-protected disks MOVE.L SonyStart,A3 ; get start of disk 1 routines MOVEM.L D1-D6/A0-A1,-(SP) ; save our registers JSR (A3) ; call UnitIO to access the disk MOVEM.L (SP)+,D1-D6/A0-A1 ; replace our registers BEQ.S @0 BSET #7,WriteProt(A1) ; the disk was write protected @0 LEA CSParam(A0),A0 ; return all drive vars except speeds MOVEQ #11,D0 ; 11 words @1 MOVE.W (A1)+,(A0)+ ; move it in a word at a time SUBQ.W #1,D0 BGT.S @1 ; leave D0=0 MOVEM.L (SP)+,D4/D6/A1/A3 BRA.S DiskDone ;------------------------------------------------------------------------- ; ; Routine: CkDrvNum ; Arguments: ; A0 (input) -- pointer to the I/O parameter block ; A1 (output) -- pointer to the sonys local vars (DCE) ; D0 (output) -- result code ; D1 (output) -- offset to drive 1, or 2's locals ;------------------------------------------------------------------------- CkDrvNum MOVE.L SonyVars,A1 ; get pointer to locals MOVE.W IOVDrvNum(A0),D0 BEQ.S @1 ; drive number must be 1 or 2 CMP.W #2,D0 BGT.S @1 MOVE.W D0,Drive(A1) ; drive in question BSR GetDrv1 MOVEQ #0,D0 RTS @1 MOVEQ #NSDrvErr,D0 ; bad drive number RTS ;------------------------------------------------------------------------- GetDrv1 MOVE.L SonyVars,A1 ; ptr to driver locals CMP.W #1,Drive(A1) ; drive 1 (internal drive)? BEQ.S @1 ; br if so MOVE.W #Drv2,D1 ; external drive's var offset RTS @1 MOVEQ #Drv1,D1 ; internal drive's var offset RTS ;------------------------------------------------------------------------- ; ; Routine: DiskPrime ; ; Arguments: A0 (input) -- pointer to control call parameter block ; A1 (input) -- pointer to device control entry ; D0 (output) -- result code ; ;------------------------------------------------------------------------- DiskPrime MOVEM.L D2-D7/A2-A4,-(SP) MOVE.L A1,A2 ; save the DCE (kwk) ANDI.W #$F01F,SR ; turn interrupts on BSR.S CkDrvNum ; check for valid drive number BNE Fini ; exit if bad drive error MOVE.W IOTrap(A0),D3 ; save I/O command AND.W #$FF,D3 ; clear out the top byte of the trap SUBQ.B #2,D3 ; 2=read,3=write => 0=read,1=write MOVE.L SonyStart,A3 ; get start of disk 1 routines MOVE.L TagBufPtr(A1),A4 ; ptr to user tag data buffer MOVE.W IOVDrvNum(A0),D4 ; which drive MOVE.W D3,DiskCmd(A1) ; save I/O command in locals MOVE.L IOBuffer(A0),D1 ; get pointer to io buffer MOVE.L IOByteCount(A0),D2 ; get # of bytes requested ;kwk MOVE.L DctlPosition(A2),D3 ; true position to read from ;(kwk) LSR.L #$7,D3 ; divide by 512 to get block position LSR.L #$2,D3 MOVE.W #1,D6 ; assume we are going to read the disk TST.W DiskCmd(A1) ; is it a read? BEQ.S DiskDo MOVE.W #2,D6 ; it is a write ;------------------------------------------------------------------------- ; the registers at this point are: ; ; x D1 pointer to io buffer (long) ; x D2 number of bytes to r/w (long) ; x D3 starting block position (word) ; x D4 drive 1, or 2 (word) ; x D6 read or write specifier (word) ; ; A0 pointer to control call parameter block ; A1 pointer to locals ; ? A2 pointer to DCE (kwk) ; x A3 entry point of Sony disk routines ; x A4 pointer to user tag data buffer ; ; x means that the register is used by UnitIO ;------------------------------------------------------------------------- DiskDo MOVEM.L D1-D7/A0-A2,-(SP) ; save our registers (kwk) JSR (A3) ; call UnitIO to access the disk MOVEM.L (SP)+,D1-D7/A0-A2 ; replace our registers BEQ.S Fini ; no errors? NEG.W D0 ; make sure all errors are negative CMPI.W #-$7,D0 ; no diskette? BNE.S @0 MOVE.W #OffLinErr,D0 ; must have been! BRA.S Fini @0 CMPI.W #-2,D0 ; no such drive installed? BNE.S @1 MOVE.W #NoDriveErr,D0 ; must have been! BRA.S Fini @1 CMPI.W #-$14,D0 ; write protected? BNE.S @2 MOVE.W #WPrErr,D0 ; must have been! BRA.S Fini @2 CMPI.W #-$17,D0 ; unable to read the disk? BNE.S Fini MOVE.W #DataVerErr,D0 ; must have been! Fini ;kwk -- update position & # read correctly TST.W D0 ; check for no errors BNE.S @3 ; don't do any updating ADD.L D2,DctlPosition(A2) ; update absolute position MOVE.L D2,IONumDone(A0) ; set # of bytes read ;(kwk) @3 MOVEM.L (SP)+,D2-D7/A2-A4 BRA DiskDone .END ; FILE START.TEXT ; MACWORKS copy ;___________________________________________________________________________ ; ; System Initialization Routines ; ; written by Larry Kenyon 11-Feb-83 ; ; This file is the top-level file for the Start.Obj code file. This ; code is the first code executed upon system power-up or reset. ; It is used to verify correct functioning of the MAC, initialize the ; OS dispatch table, initialize the basic system, and read in the boot ; blocks off the disk. ; ; ; Modification History: ; ; 11 Feb 83 LAK new today (from old Boot) ; 27 Feb 83 AJH integrated deep shit manager ; 13 Apr 83 AJH no more talk (talk is not cheap) ; 17 Apr 83 AJH added trap for plot compressed icon ; 14 Jul 83 SC Removed D0Info, D1Info1 and made inline in CritErr w/4x6 font ; ; ;___________________________________________________________________________ ;_________________________________; ; ; ; RAM-less subroutine call macros ; ;_________________________________; .MACRO BSR3 LEA @1,A3 BRA %1 @1 .ENDM .MACRO RTS3 JMP (A3) .ENDM .MACRO BSR4 LEA @1,A4 BRA %1 @1 .ENDM .MACRO RTS4 JMP (A4) .ENDM .MACRO BSR5 LEA @1,A5 BRA %1 @1 .ENDM .MACRO RTS5 JMP (A5) .ENDM .MACRO BSR6 LEA @1,A6 BRA %1 @1 .ENDM .MACRO RTS6 JMP (A6) .ENDM ;________________________; ; ; ; Start of Boot ROM Code ; ;________________________; .NOLIST .INCLUDE Tlasm-SYSEQU.TEXT .INCLUDE Tlasm-SYSERR.TEXT .INCLUDE Tlasm-SYSMACS.TEXT .INCLUDE Tlasm-GRAFEQU.TEXT .INCLUDE Tlasm-GRAFTYPES.TEXT .INCLUDE Tlasm-TOOLEQU.TEXT .INCLUDE Tlasm-TOOLMACS.TEXT .INCLUDE Tlasm-QUICKMACS.TEXT ; LisaGraf Definitions .INCLUDE Tlasm-FSEQU.TEXT ; File system Definitions .DEF MacInit,SystemError,SystemBeep,PutIcon .DEF MakeStkPB,DoEject .REF InitKbd,InitUtil,PuntDisk .REF IODone,Fetch,Stash .REF InitMem .REF EMT1010 .REF InitCrTable .REF CrsrVBLTask .REF Lvl2RTS,Lvl2Int .REF ExtAInt,ExtBInt ; primary ext/sts int handlers .REF InitQueue,KeyHandler,VBLHandler,NMIHandler .REF AdjEOF,Gt1stMatch,GtNxtMatch,OKToOpen .LIST .INCLUDE source-STARTMAIN.TEXT ; main start code .INCLUDE source-STARTINIT.TEXT ; actual boot code .INCLUDE source-STARTHOOKS.TEXT ; various file system "hook" proc's .INCLUDE source-STARTDIAG.TEXT ; diagnostic test procedures .INCLUDE source-DeepShit.Text ; deep shit manager .END ; FILE STARTDIAG.TEXT ; MACWORKS copy ;_______________________________________________________________________________ ; ; Modification History: ; ; <15Apr85> RDC Add changes for square dots update ; ;_______________________________________________________________________________ ; ROM DIAGNOSTIC ROUTINES ; ; Basic philosophy here is to do as complete a test as possible, given the time ; and code space requirements; where a useful test is time-consuming, that test ; is performed upon user request only (by pressing the mouse button for several ; seconds after power-on). The 68000 is assumed to be functional (as a complete ; test is not possible given the small code-space and complexity of the chip); ; a simple test could easily be added later if deemed desirable. The other LSI ; chips are tested at least for basic functionality. ; ; Particular care was taken to provide good RAM tests as failing RAM bits are ; more common and not very nice (RAMs are also relatively easy to test because ; of their regularity, tho time-consuming to test exhaustively). ; ; The testing of the disk drives is left to normal read/write routines and the ; use of redundant information in data storage. A boot test could be done, but ; that would require use of a known diskette (a writable one if write capability ; were to be tested) or minimally a diskette inserted in the drive. Testing ; of the external drive would also have to be resolved. I propose that the low ; level disk routines do some minimal testing, when the disk is first used. ; ; NOTES: ; - All routines return via RTS6 (A6 points to return address). ; - D0 lowest byte holds pass/fail result and CCR reflects this ; result (0 for pass). ; - For RAM tests, low word of D1 is an OR mask of bit failures ; - All interrupts should be disabled before these routines are called. ; - OVERLAY must be turned off for RAM tests. ; - Most of the RAM tests have the memory size hardwired into the program ; at 64K words, for speed (DBcc only decrements a word) and to save code. ; - A4,A7 are preserved by all routines. ; ; TESTS IMPLEMENTED: ; - ROM Checksum Test ; - RAM Byte Write Test (very basic) ; - Basic RAM Test (basic) ; - RAM Address Uniqueness Test (basic) ; - RAM Moving Inversion Test (moderately extensive) ; ; LOGIC TESTED: ; - All system RAM ; - All ROM ; ;_______________________________________________________________________________ ; ; ROM CHECKSUM TEST ; ; A0 = pointer into ROM D0 = scratch; error indicator ; A1 = pointer into ROM D1 = accumulated checksum ; D2 = counter ; D3 = checksum stored in ROM ; ; Note: this test is currently disabled - it needs buildrom utility ; support to work . . . ;_______________________________________________________________________________ ROMTest MOVEQ #0,D0 MOVEQ #0,D1 LEA Base,A0 ; point to reset PC (rom cksum) MOVE.L (A0)+,D3 ; stored checksum MOVE.W #ROMWSize-3,D2 ; and ROM size in words (adjusted to ; leave out the first long word) ROMLoop MOVE.W (A0)+,D1 ; add code as pos word-sized number ADD.L D1,D0 ; create a long-word-sized result DBRA D2,ROMLoop EOR.L D3,D0 ; should be zero RTS6 ;_______________________________________________________________________________ ; ; Routine: MemTest ; ; Called via BSR6, with A4 = test number ; ; MEMTEST sequences through four memory subtests: Bus (BUS), Write Byte (WRBYTE) ; External Addressing/Data (UNIQ), and Internal Addressing/Data (MOD3TEST). Each ; subtest has a code in the lower word of A4 that can be used to identify the ; failing subtest. Such information may be useful in determining the exact memory ; system failure. Register D1 contains the failing bit mask. ; ; Subtest codes passed in A4 upon failure. ; ; Note that the Internal Addressing test can return bad bits = FFFF, which would ; indicate an external address failure, possibly caused by a bad RAM chip, an ; address line, or the address multiplexors. ;_______________________________________________________________________________ ;_______________________________________________________________________________ ; ; BUS Subtest walks a 1 through a field of zeros 128 times and reads it back to ; test the read buss drivers. Note that if the first RAM location is bad, this ; subtest will fail, however the bad bit should be valid. ; ; A0 - address pointer D1 - Failing bits mask ; D2 - data pattern A4 - Test number ; D3 - iteration counter ; ;_______________________________________________________________________________ MemTest MOVEQ #0,D1 ; no errors ADDQ #1,A4 ; Subtest code 3 MOVE.L A3,A0 ; get RAM start address MOVEQ #1,D2 ; Walking 1 pattern for Buss test MOVEQ #127,D3 ; iteration count @1 MOVE.W D2,(A0) ; Write memory MOVE.W (A0),D1 ; Read back EOR.W D2,D1 ; Verify read BNE Exit ; Error ROL.W #1,D2 ; Rotate the bit DBRA D3,@1 ; again ;_______________________________________________________________________________ ; ; WRByte subtest exercises the write byte logic at the first RAM location. ; ; A0 - address pointer (still initialized from BUS subtest) ; D1 - Failing bits mask ; D2 - data pattern ; D3 - scratch ; A4 - Test number ; ;_______________________________________________________________________________ WRByte ADDQ #1,A4 ; Subtest code = #4 MOVE.W #$55AA,D2 ; Data pattern to D2 MOVEP D2,(A0) ; 55AA to even byte addresses MOVEP D2,1(A0) ; 55AA to odd byte addresses MOVE.L (A0),D1 ; Read long word back EORI.L #$5555AAAA,D1 ; read long word back to verify BNE Exit ; Abnormal exit ;_______________________________________________________________________________ ; ; Mod3Test tests the internal addressing and data retention ability of the memory ; chips using a worst case address flipping scheme and the infamous "modulo 3's" ; addressing pattern. ; ; A0 - address pointer low A4 - Test number ; A1 - address pointer high ; A2 - test parameter list pointer ; D0 - temporary failed bits register ; D1 - iteration count ; D2 - D6 - data patterns ; ;_______________________________________________________________________________ Mod3Test ADDQ #1,A4 ; Subtest = #5 MOVEQ #0,D0 ; Clear temp error bit reg LEA ParmList,A2 ; Fetch parameter list pointer MOVEM.L (A2),D2-D6 ; test data BSR5 Mod3 ; go first pass through MOVEM.L 4(A2),D2-D6 ; next pass data BSR5 Mod3 ; go second pass MOVEM.L 8(A2),D2-D6 ; next pass data BSR5 Mod3 ; go third pass MOVEQ #0,D1 ; clear any count residue MOVE.W D0,D1 ; align any failed bits SWAP D0 OR.W D0,D1 ; exit done CMP.W #$FFFF,D1 BNE.S Exit ;_______________________________________________________________________________ ; ; Unique subtest tests for external addressing faults and some data faults by ; writing an address into each memory location. ; ; A0 - Address pointer A4 - Test #1, Subtest #4 ; A1 - Address pointer ; D2 - iteration counter/data pattern ; D3 - scratch ;_______________________________________________________________________________ Unique ADDQ #1,A4 ; Subtest = #6 MOVE.L A3,A0 ; Start RAM address MOVE.L A0,A1 MOVEQ #-1,D2 ; Counter @1 MOVE D2,(A0)+ ; Count as address data DBRA D2,@1 ReadLP MOVE.W (A1)+,D3 ; Verify data EOR.W D2,D3 ; If any bad ones OR.W D3,D1 ; or in any bad bits DBRA D2,ReadLP ; until done BNE.S Exit ; Any failures? OR.W D0,D1 ;_______________________________________________________________________________ ; ; Exit via RTS6 with failed bits in D1. Set cc for caller. ;_______________________________________________________________________________ Exit TST D1 ; Set condition code . . . RTS6 ;_______________________________________________________________________________ ; ; Mod3 subroutine called by Mod3Test to do the actual write/read/compare ops. ; ; called via BSR5 ; ; Returns failed bits in D0 ; ;_______________________________________________________________________________ Mod3 MOVEM.L 28(A2),D1/A0-A1 ; Get counts, addresses @1 MOVEM.L D2-D4,(A0) ; Low addresses ADDA #12,A0 ; Adjust low address pointer MOVEM.L D4-D6,-(A1) ; High addresses DBRA D1,@1 ; until meet in the middle MOVEM.L 28(A2),D1/A0-A1 ; Get counts, addresses SWAP D1 ; Get read count @2 MOVEM.L (A0)+,D5-D7 ; Read three long words EOR.L D2,D5 ; Verify data EOR.L D3,D6 EOR.L D4,D7 OR.L D5,D6 ; compile data OR.L D6,D7 OR.L D7,D0 ; save in D0 DBRA D1,@2 ; until done MOVEM.L (A0)+,D5-D6 ; pick up last two long words EOR.L D2,D5 ; Verify data EOR.L D3,D6 OR.L D5,D6 OR.L D6,D0 ; save in D0 RTS5 ; exit via A5 ;_______________________________________________________________________________ ; ; ParmList consists of the data patterns loaded by MOVEM.L in MOD3TEST, enabling ; quick, single instruction loads of test parameters. The loop counts are calcu- ; lated on a 128K byte memory size. ; ;_______________________________________________________________________________ ParmList .LONG $DB6DB6DB .LONG $6DB6DB6D .LONG $B6DB6DB6 .LONG $DB6DB6DB .LONG $6DB6DB6D .LONG $B6DB6DB6 .LONG $DB6DB6DB .WORD 32768/3-1 ; Read loop count .WORD 5462-1 ; Write loop count .LONG OvlyRAM ; Overlay RAM start address .LONG OvlyRAM+$1FFFC+4 ; Overlay RAM end address + 1 ;_______________________________________________________________________ ; ; Routine: PutIcon,PutIcon1 ; ; based on Steve Capps' bitmap compression technique ; ; Arguments: A2 = screen address ; A3 = Ram offset pointer ; A4 = address of icon ; A6 = holds return address ; ; Called by BSR6. ; Used to display a compressed icon on the screen ; ; D0 and D1 must be preserved! ; ;_______________________________________________________________________ PutIcon0 ADD.L A3,A2 ; add in the RAM offset PutIcon MOVEQ #15,D3 ; There are 16 octals in an icon UNCOMP1 MOVE.L A2,A0 ; save screen start address MOVEQ #3,D2 ; reset row bytes counter CLR.L D5 ; clear for use <15Apr85> MOVE.W ScreenRow,D5 ; get bytes per row <15Apr85> UILOOP MOVE #$100,D4 ; prime D0 for 8 bit count count MOVE.B (A4)+,D4 ; load map byte from compressed image MLOOP LSR.W #1,D4 ; shift off map bit BEQ.S DONE ; byte done when = 0 BCC.S IBLACK ; dispatch on the bit CLR.B (A2)+ ; store zero in new BRA.S CHECK ; continue for all 8 bits IBLACK MOVE.B (A4)+,(A2)+ ; store byte in new CHECK DBF D2,MLOOP ; see if on scanline seam (every 4 bytes) ADDA.L D5,A2 ; bump to next scanline <15Apr85> SUBA.L #4,A2 ; minus a little bit <15Apr85> MOVEQ #3,D2 ; reset row bytes counter BRA.S MLOOP ; continue for all 8 bits DONE DBF D3,UILOOP ; do the rest of the octals in ICON ; Now unXOR the icon on the screen MOVE.L A0,A1 ; second pointer MOVEQ #30,D3 ; do 31 scanlines XLOOP ADDA.L D5,A1 ; scanline pointer <15Apr85> MOVE.L (A0),D4 ; get long from previous scanline EOR.L D4,(A1) ; xor into this scanline MOVE.L A1,A0 ; "add" rowBytes to a2 DBF D3,XLOOP RTS6 ; plot the dead Mac icon DeadMac LEA SadFace,A0 ;get address of face overlay CommonMac LEA MacIcon,A4 ;get address of Mac icon MOVE.L A0,D7 ;keep overlay address in D7 MOVE.L ScreenLow,A2 ;get approx centered screen address ADDA.W MidPoint,A2 ; <15Apr85> BSR6 PutIcon0 ;plot the icon MOVE.L ScreenLow,A2 ;get centered screen address plus some CLR.L D5 ;clear for use <15Apr85> MOVE.W ScreenRow,D5 ;get bytes per row <15Apr85> MULU #6,D5 ; <15Apr85> ADD.L D5,A2 ;face is 6 scanlines down <15Apr85> ADDA.W MidPoint,A2 ; <15Apr85> ADDQ.L #1,A2 ; and 1 over <15Apr85> MOVE.L D7,A4 ;get address of face BSR6 PutSym0 ;plot the face DonePutSym RTS5 ;return to caller ; plot the happy Mac icon HappyMac LEA HappyFace,A0 ;point to the happy face BRA.S CommonMac ;use common code ; PutSymbol plots a 16 by 12 overlay pointed to by A4 into the screen address ; pointed to by A2. The screen address may not be word-aligned, so be ; careful. PutSym0 ADD.L A3,A2 ; add in the RAM offset PutSymbol MOVEQ #9,D2 ; plot 10 lines PSLoop CLR.L D5 ; clear for use <15Apr85> MOVE.W ScreenRow,D5 ; get bytes per row <15Apr85> SUBQ #2,D5 ; minus a little bit <15Apr85> @1 MOVE.B (A4)+,(A2)+ ; plot 1 byte MOVE.B (A4)+,(A2)+ ; plot 2nd byte ADD.L D5,A2 ; bump to next scan line (ScreenRow-2 bytes) <15Apr85> DBRA D2,@1 ; loop until done <15Apr85> RTS6 ; return to caller ; compressed icon bitmaps MacIcon .BYTE $00,$57,$FF,$FF,$D5,$FF,$FF,$FF .BYTE $FF,$06,$F8,$3F,$E1,$FF,$FF,$0F .BYTE $60,$E3,$FF,$FF,$8F,$E0,$0F,$66 .BYTE $E0,$0F,$E0,$0F,$66,$E0,$0F,$E0 .BYTE $0F,$66,$E0,$0F,$E0,$0F,$66,$E0 .BYTE $0F,$E0,$0F,$66,$E0,$0F,$E0,$0F .BYTE $06,$E0,$0F,$E3,$FF,$FF,$8F,$60 .BYTE $E1,$FF,$FF,$0F,$E0,$0F,$66,$E0 .BYTE $0F,$E0,$0F,$22,$E3,$3F,$0F,$E3 .BYTE $3F,$0F,$66,$E0,$0F,$E0,$0F,$06 .BYTE $E0,$0F,$FF,$FF,$FF,$FF,$60,$F7 .BYTE $FF,$FF,$DF,$F0,$1F,$06,$F0,$1F .BYTE $F7,$FF,$FF,$DF .IF -1 .ELSE ; here is our theft protection code -- tile the screen with the "stolen" message ; first clear the screen MOVE.L ScreenLow,A5 ;get address to start plotting MOVE.L A5,A0 MOVE.W #ScrnLSize,D2 ; number of longs on the screen - 1 @1 CLR.L (A0)+ DBRA D2,@1 ; clear to white ; now initialize for the loop MOVEQ #10,D0 ;eleven rows MOVEQ #4,D7 Th3 MOVEQ #7,D1 ;8 per row Th4 MOVE.L A5,A2 ;get the base address LEA Theft,A4 ;point to the icon BSR6 PutIcon ;plot it ADDQ #8,A5 ;bump to next horizontal position DBRA D1,Th4 ;finish this row MOVE.W ScreenRow,D2 ;get bytes per row <15Apr85> MULU #31,D2 ; <15Apr85> ADD.W D2,A5 ;bump to next row (31 lines down) <15Apr85> ADD D7,A5 ;add offset NEG D7 ;toggle offset DBRA D0,Th3 ;loop Self BRA.S Self ;wait forever .ENDC DiskIcon .BYTE $00,$7F,$FF,$FF,$F5,$FE,$FF,$FE .BYTE $FF,$33,$70,$0F,$F8,$07,$F7,$03 .BYTE $FF,$BB,$F8,$70,$98,$01,$FF,$FF .BYTE $FF,$FE,$FF,$00,$07,$FF,$FF,$E0 .BYTE $0F,$FF,$FF,$F0,$FF,$FF,$FF,$FF .BYTE $FF,$FF,$FF,$0F,$77,$FF,$FF,$EF ; icon overlays HappyFace ; .WORD $0000,$0888,$0888,$0080 ; .WORD $0080,$0180,$0000,$0420 ; .WORD $03C0,$0000 .WORD $0000,$1110,$1110,$0100 .WORD $0100,$0300,$0000,$0840 .WORD $0780,$0000 SadFace ; .WORD $5028,$2010,$5028,$0000 ; .WORD $0480,$0300,$0000,$0FC0 ; .WORD $1030,$0008 .WORD $2828,$1010,$2828,$0000 .WORD $0480,$0300,$0000,$0FC0 .WORD $1030,$0008 QMark .WORD $0000,$0000,$07E0,$0FF0 .WORD $0C30,$0C30,$0070,$00E0 .WORD $01C0,$0180,$0180,$0000 .WORD $0180,$0180,$0000 XMark .WORD $0000,$0000,$1008,$381C .WORD $1C38,$0E70,$07E0,$03C0 .WORD $03C0,$07E0,$0E70,$1C38 .WORD $381C,$1008,$0000 ; FILE Starthooks.text ; MACWORKS copy ; ; MacWorks modification history ; ; 23-Apr-84 KWK Remember to replace entire DSHook procedure to patch ; several problems, including update bug with mem full ; condition (from Ramsys:msfilefix.text) ; 2-Sep-84 KWK Fix for DrawDSBox proc w/moving port around ; 7-Sep-84 KWK Replaced most of DSHook routine to incorporate May 7 ; software release fix for saving screen bits under ; the diskswitch rectangle. ; 9-Oct-84 KWK Now uses shifted destination rect when restoring screen bits ; <18Apr85> RDC Add change to use port offset from global variable ; ;_______________________________________; ; ; ; MakeStkPB utility . . . ; ;_______________________________________; MakeStkPB MOVE.L (SP)+,A0 MOVEQ #-1,D0 @1 CLR.W -(SP) ; get IO param block off stack DBRA D0,@1 ; (with IOFileName zeroed) MOVE.L A0,-(SP) MOVE.L SP,A0 ADDQ #4,A0 RTS ;_______________________________________; ; ; DrawDSBox utility . . . stack has: ; DS1 return address ; rect ptr ; DS2 return address ;_______________________________________; DrawDSBox PEA DSAlertRect MOVE.L (SP),-(SP) MOVE.L (SP),-(SP) MOVE.L (SP),-(SP) MOVE.L (SP),-(SP) _EraseRect _FrameRect MOVE.L #$00020002,-(SP) _PenSize MOVE.L #$00030003,-(SP) _InsetRect _FrameRect ; draw the border MOVE.L #$FFFDFFFD,-(SP) _InsetRect ;now calc the correct amount to move the port over. should be the topleft of ;the dsalertrect + the lisa offset (kwk) MOVE.L DSAlertRect,D0 ; get ready to calc ADD.L MidDiff,D0 ; adjust for new screen params <18Apr85> MOVE.L D0,-(SP) ; and push on stack _MovePortTo ADDQ #8,SP ; strip one ret addr, rect ptr RTS ; and return to caller of DS DrawDSBox ;_______________________________________; ; ; DoEject utility . . . shared by function ; key 1 and 2 procs . . . disk to eject ; is passed in D1 . . . from in D2: ; calls EjectNotify function as: ; ; Function EjectNotify(drive:int;caller:int):boolean; ; ; if false is returned, the disk is not ejected; ; caller=1 for eject key, caller=2 for DS hook ;_______________________________________; DoEject BSR MakeStkPB ; get a parameter block MOVE.W D1,IODrvNum(A0) MOVE.L EjectNotify,D0 ; notify proc? BLE.S @1 ; br if not MOVEM.L D2/A0-A2,-(SP) CLR.W -(SP) MOVE.W D1,-(SP) ; pass eject drive MOVE.W D2,-(SP) ; 1=fkey eject, 2=ds hook eject MOVE.L D0,A0 ; procedure pointer JSR (A0) ; call it (it should preserve Pascal regs) TST.B (SP)+ ; still want to eject? MOVEM.L (SP)+,D2/A0-A2 BEQ.S @2 ; br if not @1 _Eject ; get rid of it . . . BEQ.S @2 MOVE.W #8,-(SP) _SysBeep ; make a beep @2 ADD #IOVQElSize,SP ; clean up stack and return RTS ;------------------------------------------------------------------------ ; GNEFilter filter proc for GetNextEvent ; ; A1 = MyEvent ptr ; D0 = result ; (SP) = return to caller ; 4(SP) = result to caller ;------------------------------------------------------------------------ GNEFilter LEA AlarmState,A1 BSET #5,(A1) ; should we flash? BNE.S @1 ; br if not MOVEQ #3,D0 AND.B (A1),D0 ; both enables must be 0 (bits 0 and 1) BNE.S @1 TST.B WWExist ; also make sure we are in a normal state BNE.S @1 ; exit if none ; make sure the leftmost menu is the Apple menu MOVE.L MenuList,D0 ; got a menuList? BEQ.S @1 ; if not, skip MOVE.L D0,A0 ; get the handle MOVE.L (A0),A0 ; handle -> pointer TST.W (A0) ; how many menus? BLE.S @1 ; skip if none MOVE.L MenuOH+6(A0),A0 ; get the handle of the 1st menu MOVE.L (A0),A0 ; handle -> pointer CMP.W #$0114,MenuData(A0) ; apple menu? BNE.S @1 ; if not, skip ; we know the Apple menu is up there, so flash it MOVE.L #$00010011,-(SP) ; top,left of shield rect MOVE.L #$0013001E,-(SP) ; bottom right of shield rect MOVE.L JShieldCursor,A0 ; different param's then _ShieldCursor JSR (A0) MOVE.L ScrnBase,A0 ; start of screen MOVE.W ScreenRow,D0 ; 90 for Lisa . . . MOVE.L #$00007FFC,D1 ; xor mask MOVEQ #17,D2 ; 18 rows @0 ADD.W D0,A0 ; bump to next line EOR.L D1,(A0) ; invert DBRA D2,@0 ; loop it 18 times _ShowCursor BCHG #7,(A1) ; flip current state for alarm clock BCLR #6,(A1) ; have we beeped yet? BEQ.S @1 ; br if so MOVE.W #8,-(SP) _SysBeep @1 CkFunKey MOVEQ #0,D1 ; type MOVE.B ScrDmpType,D1 ; dump screen flag? BMI.S @1 ; just go on if not MOVE.W #$00FF,ScrDmpEnb ; disable further keys for now SUBQ #4,SP ; load in appropriate function-key package MOVE.L #'FKEY',-(SP) MOVE.W D1,-(SP) ; types 0-9 _GetResource MOVE.L (SP)+,D0 BNE.S @0 ; br if we got the resource TST.W D1 ; zero? BEQ.S @2 ; exit if so CMP.W #2,D1 ; other than 1 or 2? BGT.S @2 MOVEQ #1,D2 ; 1 means from function key JSR DoEject ; 1 and 2 are eject keys BRA.S @2 ; then exit . . . @0 MOVE.L D0,A0 MOVE.L (A0),D0 ; dereference BEQ.S @2 ; exit if purged BSET #Lock,(A0) MOVE.L A0,-(SP) ; save for unlock MOVE.L (A0),A0 ; dereference JSR (A0) MOVE.L (SP)+,A0 ; recover handle BCLR #Lock,(A0) ; let it go . . . @2 ST ScrDmpEnb ; reenable @1 RTS ;_______________________________________________________________________ ; ; Routine(s): DSHook et al ; (c) 1983 Apple Computer Inc. ; ; Arguments: A0.L (input) -- I/O parameter block ptr (call which failed) ; ReqstVol -- VCB ptr for needed volume ; FSQHead -- ptr to queue of VCBs (all mounted volumes) ; File system is ready for another call. ; All registers are preserved ; ; Function: This routine prompts the user to reinsert the volume needed ; to complete the original call. ; ; Put up dialog asking for off-line volume. ; Eject diskette in original mount drive, if any (check for DIP in drive queue). ; Then: If disk-insert event and MemFullErr then deepshit . . . ; otherwise, relaunch . . . ; ; Possibilities: ; - let feature-1 eject drive 1, feature-2 eject drive 2, etc. ; - let feature-Q cause a quit, or abort . . . ;_______________________________________________________________________ FSQHook CLR.L ReqstVol ; zero requested volume MOVE.W IOVRefNum(A0),D2 ; is a drive number specified? BLE.S @4 ; skip if not . . . CMP.B #$0F,D1 ; MountVol? BEQ.S @4 ; skip if so (drive number is cool here) ; convert the drive number to a volume refnum for volumes with maps swapped out NEG.W D2 ; look for this in the VCBDRefNum field MOVE.L VCBQHdr+QHead,D0 @1 BEQ.S @4 ; skip when no more VCBs MOVE.L D0,A1 TST.W VCBDrvNum(A1) ; is it's map swapped out? BNE.S @2 ; br if not CMP.W VCBDRefNum(A1),D2 ; do we have a mapping? BEQ.S @3 ; br if so @2 MOVE.L QLink(A1),D0 ; otherwise, check next VCB BRA.S @1 @3 MOVE.W VCBVRefNum(A1),IOVRefNum(A0) ; make the switch @4 MOVEQ #0,D0 ; zero for good luck RTS CDHook TST.W D0 BEQ.S mtvolfix TST.L ReqstVol ; requested volume not set? BNE.S @1 MOVE.L A2,ReqstVol ; fix RfnCall screwup @1 CMP.W #ExtFSErr,D0 ; for external file system? BNE.S mtvolfix ; br if not MOVE.L ToExtFS,D2 ; is there an external FS? BLE.S CDRTS ; br if not MOVE.L D2,A1 JMP (A1) ; otherwise, let it handle the call ; (CmdDone return address is on stack) mtvolfix MOVE.L FSQHead,A0 ; A0 -> current request MOVE.B IOTrap+1(A0),D2 ; trap number CMP.B #$0F,D2 ; mountvol call? BNE.S sfifix ; br if not TST D0 ; error? BNE.S @0 ; br if so (mountvol error case) TST.W -(A5) ; is buffer dirty? BMI.S @1 ; br if so CLR.W (A5) ; otherwise, invalidate it (it's the last BRA.S @1 ; file directory block) @0 TST.B NewMount ; new mount? BNE.S @1 ; exit if so (everything is ok) ADD #VCBDrvNum,A2 ; point to drive number field MOVE.W (A2),D3 CLR.W (A2)+ ; it should be zeroed MOVE.W D3,(A2)+ ; and put back into driver refnum field ADDQ #4,A2 ; bump to buffer pointers CLR.L (A2)+ ; both should be cleared CLR.L (A2)+ @1 CDRTS RTS ; that was it . . . sfifix TST.B D2 ; open call? BEQ.S openfix ; br if so CMP.B #$0A,D2 ; openrf? BEQ.S openfix ; br if so TST D0 ; error? BNE.S @1 ; error cases are not patched CMP.B #$0D,D2 ; setfileinfo? BNE.S @1 ; MOVEM.L IOFlCrDat(A0),D1-D2 ; get IOFlCrDat, IOFlMdDat MOVEM.L D1-D2,FlCrDat(A5) ; and store in FlCrDat, FlMdDat @1 RTS ; then exit . . . openfix TST D0 ; no error? BEQ.S @2 ; then branch CMP.W #PermErr,D0 ; permissions error? BNE.S @8 ; no patch for other errors TST.B IOPermssn(A0) ; asking for whatever permissions? BNE.S @8 ; exit if not (asked for write perm) MOVE.L A3,D2 SUB.L FCBSPtr,D2 ; recover refnum MOVE.W D2,IORefNum(A0) MOVE.L -14(A5),D2 ; recover file number TST.B RegRsrc ; regular part open? BNE.S @1 ; br if so MOVE.L -24(A5),D2 @1 ADDQ #4,SP PEA OKToOpen ; do it again RTS ; note res/reg flag bit is in bit 1 of D2, A0 -> pblk, A3 = FCB ptr+28, A2 = VCB ptr @2 BSET #7,5(A2) ; note that a file was once open here MOVE.W IORefNum(A0),D4 ; get refnum we are returning MOVE.W D2,D3 ; save resource/reg indication MOVE.L -28(A3),D2 ; D2 is file number JSR Gt1stMatch ; get an FCB match on D2, A2 (always 1) @5 CMP.W D1,D4 ; this one? BEQ.S @6 ; br if so MOVE.B FCBMdRByte(A1,D1),D5 ; check for same fork (and save) MOVE.B D5,D6 EOR.B D3,D6 ; bit 1 must match LSR.B #2,D6 BCC.S @7 ; br if successful @6 JSR GtNxtMatch BEQ.S @5 ; br if match BRA.S @8 ; return if no FCB matches . . . @7 JSR AdjEOF ; otherwise, make sure we are the same MOVE.B D5,FCBMdRByte(A1,D1); don't let AdjEOF change dirty bit @8 RTS ;_______________________________________; ; ; finally, here is the disk-switch hook ;_______________________________________; ; RoomToSave is the number of free bytes between the stack and the heap that we ; need to save the bits. The bitmap we fake on the stack has rowbytes = 36, for ; a rect with height $5A, thus 3240 bytes. RoomToSave .EQU 3254 ; # of bytes to save bits under box + 14 Slop .EQU 1500 ; (kwk) was 1024, needed more DSHook MOVEM.L A0-A3/A6/D0-D7,-(SP) ; save registers CLR.L DskSwtchHook ; clear this to make sure we don't reenter LEA TrapAgain,A1 ; fill in the trap now MOVE.W IOTrap(A0),(A1) ; Now set up the disk-switch alert rect such that it's shifted for the Lisa ; screen (MWDSalertRect) MOVEM.L A0/A1,-(SP) ; save regs LEA DSalertRect,A0 ; get the original DS alert rect LEA MWDSalertRect,A1 ; get addr of my rect MOVE.L (A0)+,(A1)+ ; shift top left value MOVE.L (A0),(A1) ; shift bot right value PEA MWDSalertRect ; get the rect on the stack MOVE.L MidDiff,-(SP) ; push center of screen offset <18Apr85> _OffsetRect ; and shift the rectangle MOVEM.L (SP)+,A0/A1 ; restore regs ; first try mounting the volume in case it was forced off-line due to mem-full: BSR MakeStkPB ; get a parameter block off the stack . . MOVE.L A0,D7 ; remember it in D7 MOVE.L ReqstVol,A2 ; VCB for requested volume MOVE.W VCBDRefNum(A2),D1 ; Original drive BPL.S TellUser ; br if ejected-offline NEG.W D1 ; negative means non-ejected offline MOVE.W D1,IODrvNum(A0) ; so just remount (reload the buffers) _MountVol BEQ DSExit ; exit if everything is rosy . . . TellUser MOVEQ #0,D4 ; use D4 as QDExist flag, too MOVEQ #0,D5 ; D5 flags if we saved the bits TST.B QDExist ; quickdraw around? BNE.S DrawBoxDS ; br if not MOVE.L (A5),A0 ; get quickDraw globals MOVE.L (A0),D4 ; save "thePort" ;see if there's enough room to save the bits... MOVE.L SP,D0 ; get current stack address SUB.L #,D0 ; sub off size we need MOVE.L ApplZone,A0 ; get the base of the zone CMP.L (A0),D0 ; is there enough room? BLE.S DrawBoxDS ; if not, tough luck ;there's enough toom to save off the bits so allocate the space and initialize ;the bitMap MOVE.L SP,D5 ; remember D5 & flag that we saved bits ADD.L #Slop,D0 ; don't reserve the slop MOVE.L D0,SP ; allocate the space on the stack MOVE.L D0,D6 ; remember bitmap address in D6 MOVE.L SP,A0 ; point to the bitmap PEA 14(A0) ; point to the actual bit buffer MOVE.L (SP)+,(A0)+ ; set up the base address MOVE.W #36,(A0)+ ; set up rowbytes CLR.L (A0)+ ; bounds rect topleft is 0,0 MOVE.L #$005A011D,(A0)+ ; bounds botright ;now D6 points to my bitmap. Make A6 point to a fake port to use for the ;_CopyBits call. SUB #,SP ; allocate space for grafport and fake rgns MOVE.L SP,A6 ; point A6 at port BSR DSAllocFakeRgns ; allocate fake regions MOVE.L SP,-(SP) ; push it _InitPort ; and make a port ; Now save off the bits using Copybits. MOVE.L (A5),A0 ; get grafGlobals pointer MOVE.L A6,(A0) ; set my fake port PEA ScreenBits(A0) ; source bitmap is the screen MOVE.L D6,-(SP) ; dest bitmap is our new one PEA MWDSalertRect ; source rect is the shifted deep shit rect MOVE.L D6,A0 ; point to the bitmap PEA 6(A0) ; dest rect the the stack bitmap's bounds CLR.W -(SP) ; mode is srcCopy CLR.L -(SP) ; no mask region _CopyBits ; copy those bits ; the next thing we do is invoke the DeepShit error handler. By setting the alernate draw proc, we ; force the deepshit code to call DrawDSbox, which draws the small disk-switch box and SHIFTS THE ; PORT such that 0,0 is the upper-left corner of the DSalertRect rectangle. DrawBoxDS BCLR #7,DSDrawProc ; use alternate draw proc . . . MOVEQ #DSReInsert,D0 ; ask for diskette back _SysError EjectCurDisk MOVE.L DrvQHdr+QHead,D0 ; figure out if this drive has a disk-in-place @0 BEQ.S WaitForDsk MOVE.L D0,A1 CMP.W DQDrive(A1),D1 ; find queue element for this drive BEQ.S @1 MOVE.L QLink(A1),D0 BRA @0 @1 MOVE.B -3(A1),D0 ; DiskInPlace CMP.B #1,D0 ; BEQ.S @2 CMP.B #2,D0 BNE.S WaitForDsk ; just wait for disk-insert if no DIP @2 MOVEQ #2,D2 ; a disk-switch eject BSR DoEject WaitForDsk SUB #EvtBlkSize,SP ; get event buffer space off the stack @1 MOVE.W #128,D0 ; only disk-inserted events interest us MOVE.L SP,A0 ; event buffer _GetOSEvent BNE.S @1 ; loop until we get one . . . MOVE.L EvtMessage(SP),D0 ; drive number ADD #EvtBlkSize,SP ; free up event buffer space MOVE.L D7,A0 ; point to the I/O block MOVE.W D0,IODrvNum(A0) ; drive to mount _MountVol Relaunch CMP.W #MemFullErr,D0 ; memory full? BNE.S CheckUpdate ; br if not MOVEQ #DSMemFullErr,D0 ; gookie if so _SysError ; OK, we're basically done with the disk switched stuff. Restore the bits ; on the scren if we were able to save them off. CheckUpdate TST.L D5 ; were the bits saved? BEQ.S PostUpdate ; if not, skip ; we have the bits saved off so put them back on the screen. Remember that the ; port is now shifted from the call to DrawDSrect, so we need to use a shifted ; destination rect. MOVE.L D6,-(SP) ; source bitmap is ours MOVE.L (A5),A0 ; point to QD globals MOVE.L A6,(A0) ; make our port the current one PEA ScreenBits(A0) ; dest bitmap is the screen MOVE.L D6,A0 PEA 6(A0) ; source rect is stack bitmap bounds PEA MWDSalertRect ; dest rect is the shifted deepshit rect CLR.W -(SP) ; mode is srcCopy CLR.L -(SP) ; no mask region _CopyBits ; and do it up ; deallocate the stack space and go restore the port MOVE.L D5,SP ; restore old stack pointer BRA.S RestorePort ; use common exit code ; At this point, we weren't able to save the bits so set a flag to post the update ; the next time GetNextEvent is called PostUpdate CLR.B DSWndUpdate ; flag GNE to remove the alert . . . TST.L D4 BEQ.S DSExit RestorePort MOVE.L D4,-(SP) ; restore the port _SetPort DSExit LEA DSHook,A0 ; reinstall disk switch procedure MOVE.L A0,DskSwtchHook ADD #IOVQElSize,SP ; clean up stack MOVEM.L (SP)+,A0-A3/A6/D0-D7 ; restore registers TrapAgain .Word 0 ; original trap goes here RTS ;This little routine is stolen from the deepshit rom code and used by ;the DShook code DSAllocFakeRgns LEA VisRgn(A6),A1 ;get pointer to visRgn handle LEA PortRec(A6),A0 ;point to fake master pointer MOVE.L A0,(A1)+ ;set up vis ADDQ #4,A0 MOVE.L A0,(A1)+ ;set up clip LEA DSFakeRgn,A1 MOVE.L A1,(A0) SUBQ #4,A0 MOVE.L A1,(A0) RTS DSFakeRgn .WORD 10 .WORD -30000,-30000,30000,30000 ; This rect is the disk-switch alert rectangle (DSalertRect) w/coordinates after the ; _MovePortTo in DrawDSbox has shifted the port over to the top left corner. MWDSalertRect .WORD $0000, $0000, $0000, $0000 ; File: StartInit.Text ; MACWORKS copy ;___________________________________________________________________________ ; ; System Initialization Routines ; ; written by Larry Kenyon 8-Feb-83 ; modified by Jeff Parish 83 -- 84 ; ; This file contains the system initialization routines for Macintosh. ; The entry point is MacInit, which calls various subroutines to ; do the dirty work. ; ; This contains the ROM OS code which initializes the system enough to ; boot the RAM-based system off the first two blocks of the internal disk. ; The memory is set up so: ; ; $4113FF +-------------------+ ; | | ; | Dispatch Table | ; | | ; $411000 +-------------------+ ; | | ; | Driver Globals | ; | | ; $410000 +-------------------+ ; | | ; | ROM | ; | | ; $400000 +-------------------+ ; ; ; $FFFF8 +-------------------+ ; | | ; | Lisa screen | screen boot pattern, ; | | disk request icon if needed ; | | ; $F8000 +-------------------+ ; ; ; $80000 +-------------------+ ; | sound, disk buffer| sound buffer cleared, disk ; $7FD00 +-------------------+ speed set appropriately ; | | ; | | ; | unused | ; | | ; | | ; $10400 +-------------------+ ; | boot blocks | boot blocks read in here ; $10000 +-------------------+ ; | | ; $0FE00 +-------------------+ <- Grafport for QD calls ; | | <- A5 (A5-SP = 400, QD Globals) ; $0FC00 +-------------------+ <- SP ; | | ; | stack | ; | | ; | | ; $01000 +-------------------+ ; | | ; | system globals | ; | | ; $00800 +-------------------+ ; | MacWorks globals | ; | LisaBug globals | ; $00600 +-------------------+ ; | | ; | system globals | ; | | ; $00000 +-------------------+ ; ; ;---------------------------------------------------------------------- ; ; Modification History: ; ; 9 Feb 83 LAK new today (from old Sysinit) ; 16 Feb 83 LAK removed event manager initialization. ; 28 Feb 83 AJH general code krunch ; 13 Apr 83 AJH inited dispatch table to unimplemented core routine ; 17 Apr 83 AJH rewrote boot block sequence ; 21 Apr 83 AJH fixed initing "unimplemented core routine" bug ; 22 Apr 83 AJH plotted Happy Mac after finding boot blocks ; 27 Apr 83 LAK made cursor table init routine sharable ; 27 Apr 83 AJH made InitCrsr set up PinRect vector ; 28 Apr 83 AJH removed pinRect vector (moved PinRect into crsrCore!) ; 28 Apr 83 AJH cleaned up remains of disk icon below happy mac icon ; 01 May 83 AJH made it size memory, work for 512K proto ; 02 Jun 83 SC Added init for jerked cursor ; 16 Jun 83 LAK InitIO now initializes UnitNtryCnt lomem variable. ; 23 Jun 83 LAK InitIO doesn't init Async port A driver if AppleBus configured ; in parameter ram. ; 24 Jun 83 LAK Fixed (hopefully) 23 Jun change with BCS instead of BLE. ; 26 Jun 83 AJH Integrated sound driver ; 14 Jul 83 LAK Incorporated code-saving changes found in code walkthru: ; mainly in memory sizing code and RdBootLoop. ; 15 Jul 83 LAK Further modifications to SCC init code to make cursor work. ; 06 Aug 83 BLH Moved initialization of OneOne, minusOne to here. Moved ; restartProc initialization to segLoader. ; 09 Aug 83 LAK Saved code by having InitIO use InstallDrvr, Status, and ; Open calls; no longer allocates local space for a driver. ; 11 Aug 83 LAK Moved some init stuff here from disk driver. ; 12 Aug 83 AJH Added init for MScaleThresh and Factor ; 13 Aug 83 LAK Use ,CLEAR option for UnitTable allocation to save 8 bytes. ; Changed mouse scale init for newest scheme. ; 15 Aug 83 LAK Added IWM lomem location init; added FSIODneTbl init of ; IO vectors to save one lousy word. ; 17 Aug 83 LAK Added init of JCrsrTask. ; 18 Aug 83 LAK Changed init of cursor scaling parms. ; 19 Aug 83 LAK Added init of StkLowPt. ; 20 Aug 83 SC New disk icon and fixed Qmark overlay. ; 22 Aug 83 LAK don't open the async drivers at boot time ; XX XXX 83 JWP extensively modified for MacWorks to run ; on a Lisa ; 20 Jun 84 RDC Add hard disk driver support for Profile/Widget ; 02 Jul 84 RDC Cleaned up hard disk boot stuff ; 05 Jul 84 KWK Clear TermProc low-mem var (didn't I do this before??) ; 16 Jul 84 KWK Moved BootBeep from StartMain to here, fixed length ; 18 Jul 84 RDC Add fixes for hard disk icon flashing and subsequent boot ; from floppy attempt ; 22 Aug 84 KWK Added Rich's new Hard Disk icon ; 20 Sep 84 KWK Added 'forced' boot from Sony (if option key down) ; 27 Sep 84 KWK Clear MonHeader low-mem var (set to NOT a monitor format) ; 11 Oct 84 KWK ST CrsrCoupled at init time. ; 20 Oct 84 KWK Set MouseMask to -1 at init time ; 29 Oct 84 KWK Fixed 'forced' boot from Sony ; 11 Jan 85 JWP Replace the state of Option and Command key after soft boots. ; <15Apr85> RDC Add changes for new screen size for square dots update ; <24Apr85> RDC Add setting of higher default contrast ;___________________________________________________________________________ .DEF JmpTblInit .REF Restop,FSIODneTbl .REF DiskDrvr,SoundDrvr .REF AsyncAIn,AsyncAOut,AsyncBIn,AsyncBOut HdCode .EQU 1 ; TRUE => including hard disk code (rdc) MacInit ; set up some system globals CLR.L DSAlertTab ; no deep shit alerts yet MOVE.L #$00010001, OneOne ; Set up magic constants MOVEQ #-1, D0 ; Get -1 MOVE.L D0, MinusOne ; and set up MinusOne MOVE.L #$400000,ROMBase ; initialize base address for dispatcher MOVE.B LisaRomID,D0 ; get version level of Lisa ROM <15Apr85> CMP.B #3,D0 ; is it a square dots ROM? <15Apr85> BNE.S @1 ; skip if not <15Apr85> MOVE.L #ScrnRes,ScrVRes ; set up ScrVRes, ScrHRes for square dots <15Apr85> MOVE.W #76,ScreenRow ; number of rowbytes for the MacXL screen <15Apr85> MOVE.W #431,ScrnHeigth ; screen heigth in pixels <15Apr85> MOVE.W #608,ScrnWidth ; screen width in pixels <15Apr85> MOVE.W #NewMidOffset,MidPoint ; approx center of screen <15Apr85> MOVE.L #NewMidDiff,MidDiff ; delta between square dots/mac screen <15Apr85> MOVE.L ScreenLow,A0 ; get screen address <15Apr85> MOVEQ #-1, D0 ; set all F's <15Apr85> MOVE.L D0,$7FF4(A0) ; clear extra screen bytes <15Apr85> BRA.S @2 ; <15Apr85> @1 MOVE.L #$003C005A,ScrVRes ; set up ScrVRes, ScrHRes at 60x90 dots/inch MOVE.W #$5A,ScreenRow ; number of rowbytes for the Lisa screen MOVE.W #364,ScrnHeigth ; screen heigth in pixels <15Apr85> MOVE.W #720,ScrnWidth ; screen width in pixels <15Apr85> MOVE.W #OldMidOffset,MidPoint ; approx center of screen <15Apr85> MOVE.L #OldMidDiff,MidDiff ; delta between lisa/mac screen <15Apr85> @2 MOVE.L ScreenLow,ScrnBase ; set up pointer to screen base MOVE.B #$FE,AlarmState ; set global flash enable CLR.L SPAlarm ; clear system alarm time LEA GNEFilter,A0 MOVE.L A0,JGNEFilter CLR.L IAZNotify ; no InitApplZone notify proc ; initialize the size and location of the Disk Switch alert box (80,120,170,405) MOVE.L #$00500078,DSAlertRect MOVE.L #$00AA0195,DSAlertRect+4 LEA DrawDSBox,A0 ; set up the Disk Switch box draw proc MOVE.L A0,DSDrawProc BSET #7,DSDrawProc ; and set disable flag ; point DskSwtchHook to the RAM-based disk switch hook code for the file system LEA DSHook,A0 ; disk switch procedure MOVE.L A0,DskSwtchHook LEA CDHook,A0 ; cmdDone procedure MOVE.L A0,ExtFSHook LEA FSQHook,A0 ; FSQueue procedure MOVE.L A0,FSQueueHook ; some stuff for the disk driver, too CLR.L PollProc ; no proc to handle SCC poll data MOVE.L #PWMBuffer,PWMBuf2 ; no alternate snd/pwm buffer ; size memory to figure out MemTop (note that memory has been set to all 1s ; at this time . . . MOVE.L TopOfMem,A0 MOVE.L A0,MemTop ; set up MemTop SUB #$300,A0 ; compute sound base address MOVE.L A0,SoundBase ; set up sound base address MOVE.L A0,BufPtr ; start loading code below screen CLR.L StkLowPt ; set stack low at this time ; init some I/O and driver base addresses LEA FSIODneTbl,A0 ; point to the offset table LEA JFetch,A1 ; point to 1st jump table entry MOVEQ #2,D1 ; there are 3 vectors BSR JmpTblInit ; initialize some system booleans so we can initialize the system properly ; ST SysMap ; flag that resources are not inited ; ; (memory set to $FFs now) CLR.L DskVerify ; turn off debug/Verify flags CLR.W SysEvtMask ; don't allow any events to be posted ; until events are initialized CLR.L JKybdTask ; no keyboard task yet LEA VBLQueue,A1 JSR InitQueue ; initialize VBL queue header CLR.L Ticks ; clear system tick count CLR.L MBTicks ; set timestamp for mouse button MOVE.B #$80,MBState ; set current mouse button state to "up" MOVE.B #60,Tocks ; set up the 1-sec counter CLR.L TermProc ; set terminate proc ptr to nil (kwk) CLR.W MonHeader ; SF flag to write out monitor style header to blk 0 during write ; now its time to initialize the interrupt driven keyboard handling routines and ; the vertical retrace manager. InitLvl1 LEA Lvl1DT,A1 ; this is where we will save Rick's stuff TrapTo _VBLRoutine ; get address of current VBL handler MOVE.L A0,(A1) ; save in low memory LEA VBLHandler,A0 ; install our VBL handler TrapTo _SetVBLRoutine ; set address of current VBL handler JSR InitKbd ; initialize keyboard globals TrapTo _KeyRoutine ; get address of Rick's keyboard handler MOVE.L A0,4(A1) ; save in low memory for debugger LEA KeyHandler,A0 ; install our keyboard handler MOVE.L A0,8(A1) ; also save in low memory for debugger TrapTo _SetKeyRoutine ; set address of Mac's keyboard handler MOVE.W #$60,D0 ; <24Apr85> TRAPTO _SetContrast ; set to higher contrast <24Apr85> ; special "high contrast version" .IF xContrast MOVE.W #$A0,D0 TRAPTO _SetContrast ; set to (almost) maximum contrast MOVE.W #$FF,D0 TRAPTO _SetDimContrast ; set to minimum dim value MOVE.L #$3A980,D0 TRAPTO _SetFadeDelay ; 240K milliseconds or 4 minutes .ENDC ; INITCRSR -- Cursor/Mouse initialization routine. ; turn on mouse and VBL interrupts and initialize the cursor globals (all 0's) InitCrsr MOVE.L ScrnBase,D0 ; save the ptr to the screen LEA GrafBegin,A0 ; start of global vars LEA GrafEnd,A1 ; end of global vars ClrGlob CLR (A0)+ CMP.L A1,A0 BLT.S ClrGlob ; clear out cursor globals area MOVE.L D0,ScrnBase ; replace the ptr to the screen ST CrsrCoupled ; the cursor starts out coupled (kwk) MOVE.L MinusOne,MouseMask ; set mouse mask to $FFFFFFFF LEA CrsrPin,A0 CLR.L (A0)+ ; topleft = 0,0 MOVE.W ScrnHeigth,(A0)+ ; set bottom edge <15Apr85> MOVE.W ScrnWidth,(A0)+ ; set right edge <15Apr85> ; initialize the cursor jump table with a loop. The offsets are ; obtained from a table in CrsrCore. LEA InitCrTable,A0 ; point to the offset table LEA JHideCursor,A1 ; point to 1st jump table entry MOVEQ #7,D1 ; there are 8 vectors BSR JmpTblInit ; now its time to initialize the interrupt dispatch tables LEA AutoInt6,A2 ; point to main vectors LEA Lvl2Int,A0 MOVE.L A0,(A2) ; level "2" dispatcher LEA Lvl2RTS,A1 ; default action (RTS) LEA ExtStsDT,A2 ; now fill in the 2nd level table for MOVE.L A1,(A2)+ ; SCC external/status interrupts ; LEA MV1Int,A0 ; mice get 2 vectors ; MOVE.L A0,(A2)+ MOVE.L A1,(A2)+ MOVE.L A1,(A2)+ ; LEA MH1Int,A0 ; MOVE.L A0,(A2) MOVE.L A1,(A2)+ LEA ,A2 ; fill in vectors to secondary LEA ExtBInt,A0 MOVE.L A0,(A2) LEA ExtAInt,A0 MOVE.L A0,$10(A2) ; read time and parameter ram from clock JSR InitUtil ; initialize the dispatch table from the encoded table found starting at ; "ResTop" (right after the OS) InitROMCore LEA DispatchTab,A1 ; point to Mac Trap dispatch table ; first point all traps to "unimplemented trap receiver" LEA BadTrap,A0 ; get address of "BadTrap" SUB.L RomBase,A0 ; compute offset from RomStart MOVE.L A0,D0 ; get into d-Reg LSR #1,D0 ; divide by 2, turn off high bit MOVE.L A1,A0 ; get dispatch table address MOVE #511,D1 ; there are 512 entries in trap table @1 MOVE.W D0,(A0)+ ; init one entry DBRA D1,@1 ; loop till we do them all ; OK, here is the loop where we init the table LEA Restop,A0 ; begin at the beginning... MOVEQ #0,D2 ; D2 holds "last address" TInitLoop MOVE.B (A0)+,D0 ; get the next byte BMI.S ShortOne ; if negative, its short ; handle the case of a long one ASL #8,D0 ; that was the high byte MOVE.B (A0)+,D0 ; get the low byte InitCCommon MOVE.W D0,D2 ; remember the last one in D2 BEQ.S InitCDone ; if zero, we're done MOVE.W D0,(A1) ; update the table Transparent ADDQ #2,A1 ; skip the word BRA.S TInitLoop ; loop till done ; handle the case of a short one ShortOne AND.W #$007F,D0 ; use low 7 bits BEQ.S Transparent ; if zero, ignore it entirely ADD.W D2,D0 ; add to the previous one BRA.S InitCCommon ; let common code do the rest ; OK, we've initialized the entire dispatch table. Now install the dispatcher ; by setting up the Line1010 vector InitCDone LEA EMT1010,A0 ; get address of dispatcher MOVE.L A0,LINE1010 ; initialize the memory manager and set the system heap to its default size. JSR InitMem ; init memory manager (sys zone current) ; initialize the IO system BSR InitSCC ; init SCC for cursor BSR InitIO ; init unit I/O and drivers ; RDC .IF HdCode = 1 BSR InitHdsk ; init hard disk driver .ENDC ; (RDC) MOVE #$2000,SR ; turn on interrupts ; draw the nice, gray boot screen using QuickDraw. First we must set up ; an A5 world for QuickDraw BootScreen LEA 400(SP),A5 ; leaving room for globals PEA -4(A5) ; set up LisaGraf global area _InitGraf ; Initialize LisaGraf PEA $0000FE00 ; let Grafport be above A7, A5 _OpenPort ; Open the default port MOVE.L (A5),A2 ; point to QuickDraw globals PEA Arrow(A2) ; push address of default cursor _SetCursor ; make it the current one PEA ScreenBits+Bounds(A2) ;point to screen rectangle MOVE.L (SP),-(SP) ;push a second copy _PaintRect ; Draw black screen first MOVE.L #$00100010, -(SP) ; Push the rounding factor PEA Gray(A2) ; push gray _FillRoundRect ; Fill a round rectangle gray ; plot the "happy Mac" icon to show that everythings cool _HideCursor SUB.L A3,A3 ; make sure RAM offset pointer is set up BSR5 HappyMac ; plot the happy Mac icon ; NOTE THAT A5 IS NOW BLOWN!! _ShowCursor ; now perform some initialization for the boot blocks loop ;RDC .IF HdCode = 1 ; first check if boot from hard disk CMP.W #HDRfNum,BootDrive ; hard disk online? BNE.S BootBeep ; skip if not ;(JWP) MOVE.B KeyMap+7,D0 ; load the current option key OR.B OptionSave+1,D0 ; include the state of the option key before reboot BTST #2,D0 ; was the option key down in either case? BEQ.S @0 ; no, continue hard disk setup ;(JWP) MOVE.W #DskRfN,BootDrive ; booting with sony driver BRA.S BootBeep ; continue Sony setup, fall through to RdBootLoop code @0 MOVEQ #HDDrive,D6 ; else set drive for hard disk MOVEQ #0,D4 ; setup initial flash state BRA.S RdBootLoop ; and go start boot .ENDC ;(RDC) ;kwk -- add bootbeep code here, so only makes fart sound for sony boot ; Give a beep to tell the world that the CPU works. (D0/D1 trashed) BootBeep MOVE.W #$1,D0 ; set the speaker volume to low TRAPTO _SetVolume MOVE.L #$800,D0 ; wavelength (in microsecs) MOVE.L #$100,D1 ; duration (in milliseconds) TRAPTO _Beep ; beep it ; (kwk) RdBootBlks LEA QMark,A0 ; get address of question mark sysmbol MOVE.L A0,D7 ; and keep it in D7 MOVEQ #1,D6 ; initial drive number BTST #4,SPMisc2 ; try external drive first? BEQ.S @1 ; br if set for internal ADDQ #1,D6 ; bump to external @1 MOVEQ #3,D3 ; drive switch mask MOVEQ #0,D4 ; D4 holds the flash state TST.B MBState ; if mouse button is down, eject it first BPL.S GetGDsk1 ; now try to read in the boot blocks RdBootLoop MOVE.L SP,A0 ; use space above stack, below QD globals ;RDC .IF HdCode = 1 MOVE.W BootDrive,IORefNum(A0) ; driver refnum .ELSE MOVE.W #DskRfN,IORefNum(A0) ; Sony driver refnum .ENDC ;(RDC) MOVE.W #1,IOPosMode(A0) ; position relative to start CLR.L IOPosOffset(A0) ; start at byte position 0 MOVE.L #$00010000,A1 ; save for later use . . . MOVE.L A1,IOBuffer(A0) ; load boot blocks at $00010000 MOVE.L #$400,IOReqCount(A0) ; two 512-byte blocks MOVE.W D6,IODrvNum(A0) ; set up the drive number MOVE.W D6,BootDrive ; remember the boot drive in low memory _Read ; do it synchronously BEQ GoLaunchIt ; if no error, try to launch it ; there was some kind of error when trying to read the boot blocks. See if ; the disk was offline CMP.W #OffLinErr,D0 ; no disk in place? BEQ.S GoFlashIt ; br if so CMP.W #NoDriveErr,D0 ; no disk at all? BNE.S GetGDsk1 ; br if not ; this disk isn't there at all, so toggle to the other one and stop toggling EOR D3,D6 ; toggle drive number MOVEQ #0,D3 ; no more toggling BRA.S GoFlashIt ; try the next one ; the disk was online, but there was some kind of error. Eject it and mark ; that it was a bad disk by pointing D7 to the X symbol. GetGDsk1 ;RDC .IF HdCode = 1 CMP.W #HDDrive,D6 ; don't eject if using hard disk BEQ.S @1 .ENDC ;(RDC) MOVE.L SP,A0 MOVE.W #DskRfN,IORefNum(A0); driver refnum MOVE.W #EjectCode,CSCode(A0) MOVE.W D6,IODrvNum(A0) _Control ; eject the bad diskette @1 LEA XMark,A0 ; get address of the X symbol MOVE.L A0,D7 ; point D7 to it MOVEQ #8,D5 ; D5 holds the timeout for the X ; at this point we should give the user some feedback as to whats going on ; by flashing the disk icon. GoFlashIt MOVEM.L D3-D7,-(SP) ; preserve our state registers LSR #1,D4 ; check the flash parity BCC.S @1 ; if off, skip MOVEQ #0,D7 ; plot the plain one @1 BSR.S PlotDisk ; plot the disk icon ; now restore the registers and delay for a short while DonePDisk MOVEM.L (SP)+,D3-D7 ; restore the registers MOVEQ #3,D0 ; get delay count SWAP D0 @1 SUBQ.L #1,D0 ; delay BNE.S @1 ; for a while ; advance to the next state ADDQ #1,D4 ; bump the flash parity SUBQ #1,D5 ; decrement timeout count BNE.S FlipDisk ; if non-zero, we're cool ; the timeout has expired so switch to the question mark again LEA QMark,A0 ; point to the question mark MOVE.L A0,D7 ; update D7 ; look at the other drive FlipDisk ;RDC .IF HdCode = 1 MOVE.W #DskRfN,BootDrive ; set refnum for floppy CMP.W #HDDrive,D6 ; using hard disk? BNE.S @1 ; skip if not SUBQ #1,D5 ; else decr timeout count BNE.S GoFlashIt ; and continue flashing BRA RdBootBlks ; else go try first floppy @1 .ENDC ;(RDC) EOR D3,D6 ; flip disk number BRA RdBootLoop ; if at first you don't succeed... GoLaunchIt CMP.W #$4C4B,(A1)+ ; is it true boot code? BNE.S GetGDsk1 ; go eject if its not MOVE.L A1,-(SP) ; save entry address _HideCursor BSR5 HappyMac ; plot the happy Mac ; !!!!!!!!!!!!!!!! This is a horrendous kludge used to get around another ; !!!!!!!!!!!!!!!! horrendous kludge in the 1.0 system boot blocks. MOVE.L (SP),A1 ; retrieve the launch address MOVE.W 4(A1),D0 ; look at the version word CMPI.W #$12,D0 ; anything > 12 we will leave alone BGT.S GoToIt MOVE.W #$8,D1 ; set up the world for our new entry MOVE.W #$BE,2(A1) ; change a BRA X to a BRA Y GoToIt RTS ; launch it! ; plot the disk icon with appropriate overlay (blank,qMark or cross) ; overlay pointed to by D7 PlotDisk _HideCursor MOVE.L Ticks,D0 SyncLoop CMP.L Ticks,D0 ;sync with the video BEQ.S SyncLoop ;by wait for TICKS to change LEA DiskIcon,A4 ;get address of Mac icon ;RDC .IF HdCode = 1 CMP.W #HDDrive,D6 ;using hard disk? BNE.S @2 ;skip if not LEA HdskIcon,A4 ;else reset icon ptr .ENDC ;(RDC) @2 MOVE.L ScreenLow,A2 ;get vaguely centered screen address ADDA.W MidPoint,A2 ; <15Apr85> BSR6 PutIcon0 ;plot the icon TST D7 ;is there an overlay? BEQ.S @1 ;if not, skip MOVE.L ScreenLow,A2 ;get vaguely centered screen address CLR.L D0 ;clear for use <15Apr85> MOVE.W ScreenRow,D0 ;get bytes per row <15Apr85> MULU #16,D0 ; <15Apr85> ADD.L D0,A2 ;compute place to plot it <15Apr85> ADDA.W MidPoint,A2 ; <15Apr85> ADDQ.L #1,A2 ; <15Apr85> MOVE.L D7,A4 ;point A4 at the symbol ADD.L A3,A2 ;add in RAM base address MOVEQ #14,D2 ;15 lines to plot BSR6 PSLoop ;plot it @1 _ShowCursor RTS ; receiver for unimplemented core routines BadTrap MOVEQ #12,D0 ; get DS alert ID for bad traps BRA SystemError ; invoke the DS manager ; initialize the SCC to receive mouse interrupts InitSCC MOVE.L #SCCWBase,A0 ; point to SCC base write address (chan B) MOVE.L #SCCRBase,A1 ; point to SCC base read address (chan B) MOVE.L A0,SCCWr ; set up SCC read and write base addresses MOVE.L A1,SCCRd ; in low memory for cheaper accesses RTS ; a short routine used to set up ram-based jump tables from rom-routine ; offset tables . . . JmpTblInit MOVE.L A0,D0 ; remember its address @1 MOVEQ #0,D2 ; clear high part for arithmetic MOVE.W (A0)+,D2 ; get the next offset ADD.L D0,D2 ; compute the address MOVE.L D2,(A1)+ ; install it in the jump table DBRA D1,@1 ; loop for all 8 vectors RTS ; InitIO initializes the I/O system by building the Unit Table and ; issuing initialization calls to all the component drivers. ; DriverTable is the address offset table used to inititialize ROM based drivers ; contains an offset to the driver and a word specifying the unit number NumRomDrivers .EQU 6 ; currently, there are 6 ROM-based drivers FirstUnit .EQU 3 ; unit number of first one is 3 UnitEntries .EQU 32 ; default # of entries in unit table DriverTable JMP SoundDrvr ; sound driver JMP DiskDrvr ; Sony disk driver JMP AsyncAIn ; serial port A input JMP AsyncAOut ; serial port A output JMP AsyncBIn ; serial port B input JMP AsyncBOut ; serial port B output InitIO ; first compute the size of the unit table and allocate it MOVEQ #UnitEntries,D0 ; get number of entries in unit table MOVE.W D0,UnitNtryCnt ; save for IOCore checking ASL.L #2,D0 ; 4 bytes needed per entry _NewPtr ,SYS,CLEAR ; allocate it and zero out the memory MOVE.L A0,UTableBase ; and save its address ; now step through the ROM-based driver initialization table, initializing all ROM ; based drivers LEA DriverTable,A2 ; get address of table MOVEQ #NumRomDrivers-1,D1 ; get number of entries in table MOVEQ #FirstUnit,D7 ; get first unit number InitIOLoop ADDQ #2,A2 ; skip over JMP opcode MOVE.L A2,A1 ; get current "PC" MOVEQ #0,D0 ; clear high part for address math MOVE.W (A2)+,D0 ; get the offset ADD.L D0,A1 ; compute driver address ; allocate a device control entry for the driver AllocDCE MOVE.W D7,D0 ; get unit number NOT.W D0 ; derive the refNum SUB #IOQElSize,SP MOVE.W D0,IORefNum(SP) ; for later _DrvrInstall ; get a DCE (pass refnum in D0) ; now retrieve DCE pointer MOVE.W #1,CSCode(SP) ; 'get DCE' status call MOVE.L SP,A0 _Status MOVE.L CSParam(A0),A3 ; DCE handle MOVE.L (A3),A3 ; DCE pointer ; initialize the Device Control Entry (DCE) (some of it, anyway) MOVE.L A1,(A3)+ ; put in pointer to DCtlDriver CLR.W (A3) ; clear ram-based flag in driver MOVE.B DrvrFlags(A1),(A3) ; flags from driver -> DCE DCtlFlags ; open only the disk and sound ROM-based drivers at this time CMP #5,D7 ;is it a serial one? BCC.S @1 ;if so, don't open LEA DrvrName(A1),A1 MOVE.L A1,IOFileName(SP) CLR.B IOPermssn(SP) ; r/w permissions MOVE.L SP,A0 _Open ; open it! @1 ADD #IOQElSize,SP NextUnitIO ADDQ #1,D7 ; bump unit number DBRA D1,InitIOLoop ; loop till all are done RTS ;RDC .IF HdCode = 1 ;-------------------------------------------------------------------- ; Special initialize routine for hard disk driver. ; Sets up BootDrive location with boot device (default is hard disk ; if it is connected and OK). ;-------------------------------------------------------------------- InitHdsk MOVE.L HDiskStart,A1 ; get ptr to hard disk driver MOVEQ #0,D1 ; one driver to init MOVEQ #HdskID,D7 ; setup driver id BSR.S AllocDCE ; and go init it MOVEQ #-1,D0 ; clear space for parameter block @0 CLR.W -(SP) DBRA D0,@0 MOVE.L SP,A0 ; save ptr MOVE.W #HdRfNum,D0 ; setup refnum MOVE.W D0,IORefNum(A0) MOVE.W D0,BootDrive ; save as potential boot device refnum MOVE.W #HDDrive,IODrvNum(A0) ; set drive # MOVE.W #InitCode,CSCode(A0) ; and code for init of controller _Control ; go do device init TST D0 ; any errors? BEQ.S @1 ; no, exit normally CMP.W #LisaDskErr,D0 ; Lisa disk attached? BEQ.S @1 ; treat as no error for now (may be shared) CMP.W #MWDskErr,D0 ; MacWorks direct-start disk attached? BEQ.S @1 ; yes, no error MOVE.W #DskRfn,BootDrive ; else default to Sony @1 ADD #IOQElSize,SP ; restore stack RTS ; and exit ; compressed icon for Profile hard disk HdskIcon .BYTE $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF .BYTE $FF,$FF,$0F,$7F,$FF,$FF,$FE,$F0 .BYTE $FF,$FF,$FF,$FF,$4F,$1B,$F8,$30 .BYTE $4F,$1B,$F8,$30,$0F,$FF,$FF,$FF .BYTE $FF,$20,$67,$FF,$9F,$E6,$18,$60 .BYTE $18 .ALIGN 2 .ENDC ;(RDC) ;-------------------------------------------------------------------- ; ; Procedure ScreenSize (var x: Pixels; var y: Pixels); ; ScreenSize TRAPTO _ScreenSize ; ScreenSize MOVEM.L (SP)+,A0/A1 ; return address, var y MOVE.W D1,(A1) ; vertical dimension MOVE.L (SP)+,A1 ; var x MOVE.W D0,(A1) ; horizontal dimension JMP (A0) ; return ;-------------------------------------------------------------------- ; File: StartMain.Text ; MACWORKS copy ;___________________________________________________________________ ; ; StartMain must be placed at the very beginning of ; the ROM. It contains the hardware start vectors ; and low level initialization code. ; ; written by Larry Kenyon, Feb 1983 ; ; Modification History: ; ; 27-Mar-83 AJH New bootBeep, code krunch, etc. ; 13-Apr-83 AJH Made beep shorter, got rid of Talk jump ; 17-Apr-83 AJH Made emergency eject do drive 2 ; 17-Apr-83 AJH made it set screen to black before beep ; 20-Apr-83 AJH removed disk vectors from jump table; made CritErr ; increment the screen to show signs of life. ; 29-Apr-83 AJH made CritErr force the disk off ; 01-May-83 AJH made things work on 512K proto ; 23-Jun-83 AJH removed emergency disk eject, and IWM init ; 13 Jul 83 LAK added changes suggested at code walkthru: added back ; longmemtest, removed rammovin test completely, ; numerous code changes as suggested. ; 13 Jul 83 SC Removed D0Info, D1Info1 and made inline in CritErr w/4x6 font ; 06 Aug 83 LAK Added IWM initialization back in. ; 06 Aug 83 SC Hacked out BootBeep for general call(SystemBeep in DeepShit) ; 16 Aug 83 SC Added duration to BootBeep ; 20 Aug 83 AJH Enters DeepShit through alternate entry point ; Changed $40000A restart to really reboot ; 23 Aug 83 LAK Reenabled ROM checksum test. ; XX XXX 83 JWP Heavily modified for MacWorks. ; 22 Apr 84 KWK Bumped rev number for next release of MacWorks: 4/1/84 ; release = $69, next release (June 84?) = $70 ; 25 Apr 84 KWK Bumped rev number again, as 4/1 or 4/6 release version ; number = $70 (what the hell was version 69?) ; 17 Jul 84 KWK Moved BootBeep code to StartInit (bypassed for hrddsk boot) ; 9 Nov 84 KWK Bumped rev number to $80, Rev C version 0.91 ; Note: Must stay $80 for Hard Disk Install to work! ; 11 Dec 84 KWK Removed Paint It Black from main init path ; 11 Jan 85 JWP Initialize OptionSave to 0 only when we hard boot ; <15Apr85> RDC Add changes for square dots update, new rev # ;___________________________________________________________________ .PROC LTest,0 .ORG 0 ; org'ed at 0 but runs at $400000 Base BRA.S PreBoot ; actual first byte of rom .WORD $0000 ; filler .WORD $0040 ; .WORD AfterBoot ; starting PC for a Reboot Version .WORD $81FF ; Lisa version in hi-byte ; (word @ location $400008) ; ROM routine jump table BRA AfterBoot ; $40 000A - reboot BRA GetGDsk1 ; $40 000E - eject disk, and reboot ; ;------------------------------------------------------------------------------- ; PreBoot TST.B MacJmp ; is LisaBug around? BEQ.S CopyROM ; no - don't enable an NMI key MOVE.W #47,D0 ; enable switching between screens TRAPTO _SetToggleKey MOVE.W #$21,D0 ; enable the NMI key TRAPTO _SetNMIKey ; ; Copy the "ROM" code from where it was loaded to $400000 (logical). ; CopyROM LEA Base,A0 MOVE.L #$400000,A1 LEA StartBoot-Base(A1),A2 MOVE.W #$4000,D0 ; copy 64k byte ROM to final pos. @1 MOVE.L (A0)+,(A1)+ SUB.W #1,D0 BNE.S @1 SUB.L #16,A0 ; back off slightly MOVE.L A0,TopOfMem ; save top of memory CLR.W OptionSave ; start off in a clean state (JWP) ; eject the preboot diskette MOVE #$2000,SR ; turn on interrupts MOVE.L SonyStart,A0 ; get start of disk #1 routines MOVE.W #5,D6 ; eject command MOVE.W #1,D4 ; eject drive #1 JSR (A0) ; go ahead and eject it! @2 TST.B SonyDone ; wait for cmd complete BNE.S @2 MOVE #$2700,SR ; turn off interrupts JMP (A2) ; jump into the "ROM" code AfterBoot MOVE #$2700,SR ; turn off interrupts LEA Lvl1DT,A1 ; point to dispatch table MOVE.L (A1)+,A0 ; get Rick's vbl handler TrapTo _SetVBLRoutine ; set address of current VBL handler MOVE.L (A1)+,A0 ; get Rick's keyboard handler TrapTo _SetKeyRoutine ; set address of Mac's keyboard handler ; fall through to StartBoot ; ;------------------------------------------------------------------------------- StartBoot MOVE.L #SCCRBase,A1 ; point to SCC base read address (chan B) MOVE.B (A1),D2 ; read to make sure SCC is sync'ed up MOVE.L #SCCWBase,A0 ; point to SCC base write address (chan B) MOVE.L #SCCWBase,A0 ; delay MOVE.B #$09,(A0) ; write register 9 MOVE.L #SCCWBase,A0 ; delay MOVE.L #SCCWBase,A0 ; delay MOVE.B #$C0,(A0) ; Force Hardware Reset SUB.L A3,A3 ; get RAM start address (= 0) MOVE.L ScreenLow,A2 ; point to the screen ; BSR6 BlackScreen ; Paint It Black (c) 1966 Jagger/Richards (removed kwk -- 12/11/84) BRA SysInit ; continue to boot ; We found a nasty error so draw the dead Mac icon and some numbers CritErr MOVE.L ScreenLow,A2 ; start at the top of the screen BSR6 BlackScreen ; clear display screen before we write on it MOVE A4,D0 ; get failing test number in D0 BSR5 DeadMac ; plot the dead Mac (preserve D0,D1) CLR.L D2 ; clear for use <15Apr85> MOVE.W ScreenRow,D2 ; get bytes per row <15Apr85> ; This plots 6 nibbles on screen contained in D0/D1. The first two digits are the ; test number that failed and the last four digits are the code (eg. bad bit #'s, ; etc.) SWAP D0 ; put test number in high word MOVE D1,D0 ; put code in low word LSL.L #8,D0 ; position in high bits ; A2 points to screen at "vaguely centered" plus 34 scanlines -1 for extra digit MOVE.L ScreenLow,A2 ; get address of top of screen MOVE.L D2,D4 ; get bytes per row <15Apr85> MULU #34,D4 ; compute plot point <15Apr85> ADD.L D4,A2 ; <15Apr85> ADDA.W MidPoint,A2 ; final offset to icon <15Apr85> SUBQ.L #1,A2 ; <15Apr85> MOVEQ #5,D4 ; size digits to plot MOVE.L D2,D6 ; get bytes per row <15Apr85> MULU #6,D6 ; compute offset between chars <15Apr85> SUBQ #1,D6 ; <15Apr85> nextDigit ROL.L #4,D0 ; get nibble in low order MOVE D0,D5 ; get into working register AND #$F,D5 ; isolate the nibble MULU #3,D5 ; 3 bytes per digit LEA numFont(D5),A1 ; point to start of digit's map MOVEQ #-61,D1 ; now mask off extras with $C3 MOVEQ #2,D3 chLoop MOVE.B (A1),D5 ; get the next byte LSR #2,D5 ; get high nibble OR D1,D5 MOVE.B D5,(A2) ADD D2,A2 ; next scan line <15Apr85> MOVE.B (A1)+,D5 ; get the next byte LSL #2,D5 ; get low nibble OR D1,D5 MOVE.B D5,(A2) ADD D2,A2 ; next scan line <15Apr85> DBRA D3,chLoop SUB D6,A2 ; point to next char <15Apr85> DBRA D4,nextDigit ; and go plot it MULU #8,D2 ; position E 8 lines down <15Apr85> ADD D2,A2 ; <15Apr85> deadLoop ADDQ.L #1,D0 SWAP D0 MOVE.B D0,(A2) ; plot 3rd byte MOVE.B (A2),1(A2) ; symmetry is nice SWAP D0 BRA deadLoop ; The digits 0-F are 4x6 bitmaps stored as 3bytes/digit numFont .BYTE $96,$42,$69 ; 0 .BYTE $B3,$BB,$B1 ; 1 .BYTE $96,$ED,$B0 ; 2 .BYTE $0E,$9E,$69 ; 3 .BYTE $66,$60,$EE ; 4 .BYTE $07,$1E,$69 ; 5 .BYTE $87,$16,$69 ; 6 .BYTE $0E,$DD,$BB ; 7 .BYTE $96,$96,$69 ; 8 .BYTE $96,$68,$E1 ; 9 .BYTE $96,$60,$66 ; A .BYTE $16,$16,$61 ; B .BYTE $87,$77,$78 ; C .BYTE $16,$66,$61 ; D .BYTE $07,$17,$70 ; E .BYTE $07,$17,$77 ; F ; next come some exception routines. "ToDeepShit" pulls off the return ; address to figure out which one it was GenExcps BSR.S ToDeepShit ; bus error BSR.S ToDeepShit ; address error BSR.S ToDeepShit ; illegal instruction BSR.S ToDeepShit ; zero divide BSR.S ToDeepShit ; check instruction BSR.S ToDeepShit ; trapv instruction BSR.S ToDeepShit ; privilege violation BSR.S ToDeepShit ; trace BSR.S ToDeepShit ; line 1010 BSR.S ToDeepShit ; line 1111 BSR.S ToDeepShit ; other exceptions IRQException ADDQ #2,SP ; pop off the status register BSR.S ToDeepShit ; interrupt exceptions ; ; BlackScreen fills the screen with black, naturally ; BlackScreen MOVEQ #-1,D3 ; black MOVE.W #scrnLSize-1,D2 ; number of longs on the screen - 1 @1 MOVE.L D3,(A2)+ DBRA D2,@1 ; blacken it to preserve phosphor RTS6 ; ToDeepShit receives all the hardware exceptions. It derives the ; deepShit ID from the return address on the stack and then invokes the ; deepShit manager ToDeepShit ; MOVEM.L A0-A7/D0-D7,$7FC80 ; save all regs for debug LEA GenExcps,A0 ; get address of receiver table MOVE.L (SP)+,D0 ; get return address SUB.L A0,D0 ; compute delta LSR #1,D0 ; divide by 2 BRA SysErr2 ; go to deepShit manager (alternate entry) ; we passed the testing of critical system components, so on to initialization ; first set up the exception vectors, then clear memory to all ones... SysInit TST.B MacJmp ; is LisaBug around? BNE.S ClearMem ; yes - don't muck with exception stuff ; LisaBug must not exist so set up RAM exception vectors ourselves MOVE.L #8,A0 ; vectors start at 8 LEA GenExcps,A1 ; first set up 7 general exceptions MOVEQ #6,D0 @2 MOVE.L A1,(A0)+ ADDQ.L #2,A1 DBRA D0,@2 ADDQ.L #2,A1 ; skip past the Trace exception ADDQ.L #4,A0 MOVE.L A1,(A0)+ ; Line 1010 ADDQ.L #2,A1 MOVE.L A1,(A0)+ ; Line 1111 ADDQ.L #2,A1 MOVEQ #12,D0 Othr1Loop MOVE.L A1,(A0)+ ; set up some 'others' DBRA D0,Othr1Loop ; LEA IRQException,A2 ; then set up the 7 autovectors ; MOVEQ #6,D0 ;IOELoop ; MOVE.L A2,(A0)+ ; DBRA D0,IOELoop ; ; ADD.L #$1C,A0 ; skip the interrupt vectors ; MOVEQ #31,D0 ;Othr2Loop ; MOVE.L A1,(A0)+ ; set up the rest of the 'others' ; DBRA D0,Othr2Loop ; ; now clear memory (most of) ; ClearMem MOVE.W #$100,A0 ; start near bottom of memory MOVEQ #-1,D1 MOVE.W #$C0,D0 ; clear up to debugger at $400 @3 MOVE.L D1,(A0)+ SUB.W #1,D0 ; decrement counter BNE.S @3 ; loop till done MOVE.L TopOfMem,D2 ; calculate how much left to clear MOVE.L #$800,A0 ; start clearing after debugger globals SUB.L A0,D2 LSR.L #2,D2 ; compute number of longs of memory @4 MOVE.L D1,(A0)+ ; set memory to negative ones ($FF) SUB.L #1,D2 ; decrement counter BNE.S @4 ; loop till done OffOverlay MOVE.L #$0000FC00,SP ; put the stack below $10000 ; fall thru to boot code (in StartInit) ; FILE Stub.text ; MacWorks source ; ; For the non-debugging version of MacWorks, the Bootconfig.data file ; on the MacWorks sony specifies that Stub.obj is loaded instead of ; Lisabug/LisaBug2 ; ; .INCLUDE tlasm-DBUGEQU.TEXT ; ; PROCEDURE STARTUP ; ; entry point to the debugger ; .PROC STARTUP,0 ; MOVE.L (A7)+,RTNADDR ; save return address to boot rom MOVE.W #$2700,TRAPSR ; make sure interrupts are off ; ; Copy monitor/lisabug globals from [$100, $300] to [$600, $800] for Mac. ; MOVE.W #$80,D0 ; copy 128 longs MOVE.W #$100,A0 ; from $100+ MOVE.W #$600,A1 ; to $600+ COPYLP MOVE.L (A0)+,(A1)+ ; copy next long SUB.W #1,D0 BNE.S COPYLP ; ; Zap 64 bytes (ie. 16 longs - the Lisa/Mac secondary dispatch) at $192 with -1 ; MOVE.W #16,D0 ; copy 16 longs of -1 MOVE.L #-1,D1 MOVE.W #$192,A1 ; to $192+ FILLLP MOVE.L D1,(A1)+ ; fill next long SUB.W #1,D0 BNE.S FILLLP EXIT LEA JUNK,A0 MOVE.L A0,$10C JUNK MOVE.L RTNADDR,A0 ; get return address JMP (A0) ; return to boot rom ; .END ; FILE VBLCORE.TEXT ; MACWORKS Copy ;----------------------------------------------------------------------- ; ; This file contains the core routines pertaining to the vertical ; retrace manager. VINSTALL installs a routine into the vertical ; retrace task list while VREMOVE removes it. ; ; written by Andy Hertzfeld 05-May-81 ; ; MODIFICATION HISTORY: ; ; 17-sep-81 bmw vinstall returns zero in d0 if it's happy ; 04-Jun-82 LAK use phase in VINSTALL to determine initial count ; 26-Jul-82 LAK phase of zero specifies no offset (used for exact one ; shots) - mod to VINSTALL ; 18-Jun-83 AJH saved 2 bytes by moving CoreStub ; 08-Aug-83 LAK added a comment only. ; 1-Nov-84 KWK inline VInstall patch for Modulo 65536 problem ; ;------------------------------------------------------------------------ .INCLUDE Tlasm-SYSEQU.TEXT .INCLUDE Tlasm-SYSERR.TEXT .DEF VINSTALL,VREMOVE .REF ENQUEUE,DEQUEUE .DEF CORESTUB ;stub for unimplemented routines .PROC VBLCORE,0 ;------------------------------------------------------------------------ ; ; Routine: VINSTALL ; ; Arguments: A0 (input) : address of vertical retrace control block ; D0 (output): error code - 0 no error ; -2 invalid queue element type ; ; Function: Installs a vertical retrace routine which is called after ; VBLCOUNT(A0) video frames. If VBLPHASE(A0) is non-zero (between ; 1 and VBLCOUNT(A0), inclusive), a phase offset will be added ; to the initial count which will be between 0 and VBLCOUNT(A0)-1, ; depending upon the current TICKS count; up to VBLCOUNT(A0) ; routines may be installed with different phases and invoked ; after different vertical retrace interrupts. ; ; Registers Used: D0,D1,A0,A1 ;------------------------------------------------------------------------ VINSTALL CMP #VTYPE,VBLTYPE(A0) ;is it the proper type? BEQ.S VIOK ;if so,skip VTYPWRONG MOVEQ #VTYPERR,D0 ;flag the error RTS VIOK MOVE.W VBLCOUNT(A0),D1 ;form rem(ticks/count) BEQ.S @2 ;avoid divide by zero ; kwk -- install modulo problem patch (avoid TICKS > 65536 as DIVU loses significant bits) MOVEQ #0,D0 ;clear out ticks count MOVE.W TICKS+2,D0 ;get TICKS MOD 65536 DIVU D1,D0 ;form TICKS/VBLCOUNT SWAP D0 ;then get the remainder MOVE.W VBLPHASE(A0),D1 ;first do some phase biasing BEQ.S @2 ;but only if phase is non-zero SUB.W D1,D0 ;subtract the phase ADDQ #1,D0 ;and add 1 for offset BPL.S @1 ;if positive, we're ok NEG D0 ;otherwise, make it positive @1 ADD.W D0,VBLCOUNT(A0) ;and bias the count @2 LEA VBLQUEUE,A1 ;get address of queue JSR ENQUEUE ;install it in the queue MOVEQ #0,D0 ;flag the non-error RTS ; and return... ;----------------------------------------------------------------------- ; ; The VREMOVE core routine removes a vertical retrace control block from the ; VBL queue. On entry, A0 points to the control block. D0 returns the error ; code; all other registers are preserved. ; ;----------------------------------------------------------------------- ; VREMOVE CMP #VTYPE,VBLTYPE(A0) ;is it the proper type? BNE.S VTYPWRONG ; MOVE.L A1,-(SP) ;preserve A1 LEA VBLQUEUE,A1 ;get address of queue JSR DEQUEUE ;remove it from the queue MOVE.L (SP)+,A1 ;restore A1 CoreStub RTS ;return DeQueue error code ; .END  RTS lab_2 CLR.B HfsFWorkshopDTR/LisaRSC01SCOMSC01SCOMXTop MOVE.L #$510,D0 _NewPtr ,Sys, Clear; (D0/byteCount:Size):A0\Ptr BNE com_1 ADDA.L #$Smartcom II / Macintosh V2.2 B@F      ןrr  Untitledwlwlwkw^rrrrrrrrrrwkw*w*w]wkwkrrw!w"w"w"w"w"w"w"w" w" w" w" w" w"w"w"w"w#w#w#w#w#w#w#w#w#w#w#w#w#w#w# w#!w#"w##w#$w#%w#&w#'w#(w#)w#*w#w%w%w%w%w%w%w%w%w% w% w% w% w% w%w%w%w%w&w&w&w&w&w&w&w&w&w&w&w&w&w&w& w&!w&"w&#w&$w&%w&&w&'w&(w&)w&*w&+w&,w&-w&.w&/w&0w&1w&2w'w>w?w?w?w?w?w?w?w?w? w? w? w? w? w?w?w?w?w?w?w?w?w?w?w?w?w?w@w@w@w@w@wAwAwAwAwAwAwAwBwBwBwBwBwBwBwBwB wB wB wB wB wBwBwBwBwBwBwBwBwBwBwBwBwBwBwBwCwCwCwC wC!wC"wC#wC$wC%wC&wCwEwEwEwEwEwEwEwEwE wE wE wE wE wEwEwEwEwEwEwEwEwEwEwEwFwFwFwFwFwFwFwF wF!wF"wF#wF$wF%wF&wF'wF(wF)wF*wF+wF,wF-wF wH wH wH wH wH wH wH wH wH  wH  wH  wH  wH  wH wI wI wI wI wI wI wI wI wI wI wI wI wI wI wI wI wI wI  wI !wI "wI #wI $wI %wI &wI 'wI (wI )wI *wI +wI ,wI -wI .wJ /wJ 0wJ 1wJ 2wJ 3wJ 4wJ 5wJ 6wJ 7wJ 8wJ 9wJ :wJ ;wJ wJ ?wJ @wJ AwJ BwJ CwJ DwJ EwJ wW wX wX wX wX wX wX wX wX  wX  wX  wX  wX  wX wX wX wX wX wX wX wX wX wX wX wX wX wX wX wY wZ wZ wZ wZ wZ wZ wZ wZ wZ wZ wZ wZ w[ w[r