mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-11-22 19:31:02 +00:00
766 lines
31 KiB
Plaintext
766 lines
31 KiB
Plaintext
;
|
||
; File: PrintGlue.a
|
||
;
|
||
; Contains: This code is the printing glue for 128K ROM printing
|
||
;
|
||
; Copyright: © 1985-1993 by Apple Computer, Inc. All rights reserved.
|
||
;
|
||
; Change History (most recent first):
|
||
;
|
||
; <SM4> 6/28/93 kc Roll in Ludwig.
|
||
; <LW2> 6/25/93 fau (with mal and chp): If the PDEF is 32 bytes or less, go flush
|
||
; the cache, in case the developer is using the PDEF as a stub and
|
||
; stuffing their own code.
|
||
; <SM3> 11/5/92 SWC Changed PrEqu.a->Printing.a and
|
||
; PrintCallsEqu.a->PrintTrapsEqu.a.
|
||
; <SM1> 6/15/92 CSS Take out forRom and CubeE conditionals because the forRomed code is old
|
||
; and this is CubeE. The net effect of which is to make printing work
|
||
; on SuperMario!!!!!
|
||
; <17> 12/16/91 IH Fix 1018177 in theFuture. Search for symbol "PURGEALIAS". Do
|
||
; not release the print driver alias and make it non-purgable
|
||
; before calling ResolveAlias.
|
||
; <16> 11/27/91 DTY Don’t save LastSPExtra around _HOpenResFile any more now that
|
||
; _HOpenResFile checks to see if the font caches should be
|
||
; flushed.
|
||
; <15> 10/4/91 gbm #1013134,#1013156: Work around a case where the font caches
|
||
; would get flushed repeatedly during printing
|
||
; <14> 3/6/91 NB Bug: NB-3. Reviewed by csd. An earlier fix to error handling
|
||
; caused the error to not be overwritten if it was already set.
|
||
; However, since PrOpen doesn't reset the error to noErr at
|
||
; startup, any printing error that stays in low-mem after closing
|
||
; the printing manager prevents subsequent printing calls. Now
|
||
; PrOpen (actually PrOpenDrvr) will reset the error to noErr
|
||
; before opening the driver.
|
||
; <13> 3/5/91 PN Fix the warning by putting back the END statement at the end
|
||
; <12> 3/1/91 NB If the resource for the alias is not found, then we would
|
||
; normally return resNotFound. The glue used to return fnfErr
|
||
; whenever it couldn't open the driver and applications have coded
|
||
; for that error. Rather than add an error code, we map
|
||
; resNotFound to fnfErr and save the user some grief. We also put
|
||
; PrError into D0 at exit. This is needed because PrLoadDriver
|
||
; returns the error in D0.
|
||
; <11> 2/21/91 NB Bug: NB-2. Reviewed by dba. Fixed a bug in PrLoadDriver in which
|
||
; it was overwriting the error. This would occasionally cause a
|
||
; cancel request from the user (iUsrAbort) to be replaced with
|
||
; noErr. Now it preserves the error if the error is already set.
|
||
; <10> 8/9/90 CCH Added System 6 print glue back in, conditionalized for ROM only.
|
||
; <8> 8/1/90 gbm fix Darin “BoneHead” Adler’s “optimization”
|
||
; <7> 7/23/90 dba change this into a linked patch
|
||
; <6> 7/20/90 gbm get rid of the warning
|
||
; <5> 5/18/90 PP Pass address of “fromFile” correctly to ResolveAlias call.
|
||
; <4> 4/17/90 NB Removed GetResource error messages when the alias is not present.
|
||
; Fixed a bad cleanup condition (called ReleaseResource on a nil
|
||
; handle on an error (no harm, though)).
|
||
; <3> 4/10/90 NB Missed a TST.W D0. Without which, the condition codes for the
|
||
; BNE.S which followed weren't always right. This caused
|
||
; occasionally stack explosions.
|
||
; 4/9/90 Nik Added call to PrLoadDriver. This loads in the driver based on
|
||
; the 'alis' -8192 resource in the system file, rather than on the
|
||
; system printer string. OpenResFile and .Print also make this
|
||
; call, instead of doing it themselves.
|
||
; <1.2> 9/20/89 CCH Rolled in System version from System sources.
|
||
; <1.3> 8/28/89 SES Removed references to nFiles.
|
||
; <1.2> 8/4/89 NMB Restored to 6.0 version of PrGlue. Ginsu is no longer in the 7.0
|
||
; builds of the system (sigh). The glue is now a ptch, rather than
|
||
; part of Rom7xFix.a, at least....
|
||
; <1.1> 5/8/89 NMB Gutted the whole thing and replaced it with a new glue which
|
||
; supports the new printing manager (Ginsu)
|
||
; <1.0> 11/16/88 CCH Added to EASE.
|
||
; 2/22/87 Jay 1). Restore curMap before jumping into the print code. This used
|
||
; to be done after comming back from the print code. The reason
|
||
; for this fix is that by leaving curMap pointing to us we might
|
||
; kick the application out of the resource search path. What if we
|
||
; need a resource out of the application file while we are inside
|
||
; the print code? 2). Also, under PrintOpen, Move PrintVars+iPrErr
|
||
; to d0 instead of testing it. This is because if PrDrvrOpen
|
||
; failed then it puts the error is in low memory but D0 (which is
|
||
; also the error) gets written over on the way out from
|
||
; PrDrvrOpen. PrintOpen tests low memory and if it is an error,
|
||
; goes to LLOut which puts D0 in low memory! D0 at this point is
|
||
; bad and the application does not get the correct error code. 3).
|
||
; Save curMap in a3 before getting the PDEF resource the first
|
||
; time.
|
||
; 2/13/87 Jay 1). Fixed a BAD bug with stack corruption on error exit if the
|
||
; printer resource file does not exist in the system folder. - In
|
||
; OpenRF, return _OpenRFPerm error in d0 - Removed ResErr check
|
||
; after OpenRF call under OpenPrRF. The error is already in d0. -
|
||
; Under OpenPrRF, if we have an error from OpenRF, put that error
|
||
; in low memory and branch to GlueAbort. It used to bne to LLOut.
|
||
; - Cleaned up GlueOut to eliminate call to _BlockMove. 2). Don't
|
||
; close the driver during PrClose. Close the resource file only.
|
||
; This is to eliminate the overhead of going thru .Print
|
||
; everytime. NOTE: The old PrLink used to leave the driver open.
|
||
; It must have been changed when PrLink was changed to PrGlue (I
|
||
; think!). - Removed call to _PrDrvrClose from PrintClose.
|
||
; 12/23/86 Jay If the GetResource call to get a PDEF fails, don't give up. The
|
||
; printer resfile may not be in the resource search path. Save and
|
||
; restore the user resource map around the GetResource (for PDEF)
|
||
; call. Get the printer resfile refnum from the low memory print
|
||
; var ($944+$E) or open the printer resource file to get it. After
|
||
; opening the printer resource file, save the refnum in low
|
||
; memory. The code to get the printer resfile refnum is now in a
|
||
; procedure called OpenRF. Check the print error after _PrDrvrOpen
|
||
; call in PrintOpen.
|
||
; 11/7/86 Jay Fixed bugs in PrDrvrDCE and PrDrvrVers. Put the result on the
|
||
; stack at (sp) instead of at 12(a6). Then, jump to GlueOut
|
||
; instead of LLOut. Changed Bra.s at PrOCerr to Bra.
|
||
; 11/7/86 Jay Fixed bug in PurgePr and NoPurgePr. Check the lower byte of
|
||
; flags to see if the driver is RAM based.
|
||
; 8/1/86 David Added PrGeneral call
|
||
; 9/17/85 Leo Converted to Ira's New Assembler
|
||
; 9/10/85 Leo New trap files, added GoSetVol Changed this file to PrintGlue.a
|
||
; no include files
|
||
; 8/17/85 Leo Integrated PrScreen, went to single Trap and selector.
|
||
; 8/6/85 Leo Added calls to SetVol/GetVol
|
||
; 7/16/85 Leo Fixed bug with stripping return values Removed PrCfgDialog Fixed
|
||
; values in PrGlueTable
|
||
; 7/13/85 Leo from old PrLink
|
||
;
|
||
; This code is the printing glue for 128K ROM printing
|
||
; calls. In this ROM, there is a single trap for printing,
|
||
; which is this code. This code takes the selctor, which
|
||
; is the last parameter to every printing call, and
|
||
; dispatches to the correct routine.
|
||
;
|
||
; There are two types of printing routines: those related
|
||
; to the high-level (PrOpenPage, etc.) interface, and
|
||
; those related to the low-level (driver calls) interface.
|
||
; The low-level interface calls are also referred to as
|
||
; 'non-link' routines throughout the comments, for reasons
|
||
; which totally escape me.
|
||
;
|
||
; The high-level interfaces are handled as one block,
|
||
; collectively referred to as PrGlue. These routines
|
||
; simply fetch the appropriate PDEF resource from the
|
||
; current printer resource file, and jsr to a certain
|
||
; offset into the resource. Which PDEF to use and
|
||
; how far into the PDEF to Jsr to are recorded in
|
||
; PrGlueTable, along with useful information like
|
||
; the number of bytes of parameters and return value
|
||
; there are for each entry. This information is used
|
||
; to allow PrGlue to build a stack frame for the routine
|
||
; and call the PDEF, after which it copies the return
|
||
; information back up on the stack and returns.
|
||
;
|
||
; The non-link routines are mostly calls on the
|
||
; .Print driver. They get themselves a iopb and
|
||
; make the call, or twiddle some aspect of the
|
||
; driver. The routines that fool with the DCE
|
||
; of the driver or the handle to the driver itself
|
||
; get the DCE by making a Status call on the
|
||
; driver, and pulling the DCEPtr out of the CSParam
|
||
; area of the iopb.
|
||
;
|
||
; PrOpen and PrClose are high-level routines that
|
||
; do not dispatch to a PDEF. They are responsible
|
||
; for opening/closing the current printer resource file.
|
||
; They also Open/Close the .Print driver.
|
||
;
|
||
; These routines are called with a final parameter,
|
||
; in addition to the ones listed in Inside Mac.
|
||
; As the last parameter, they take a longword
|
||
; full of information. The format of this long
|
||
; is like so:
|
||
;
|
||
; 31 23 15 7 0
|
||
; +--------+--------+--------+--------+
|
||
; |xxxxxxxx|xxxxxxxx|xxxxxxxx|xxxxxxxx|
|
||
; +--------+--------+--------+--------+
|
||
; Bits 31-27: Selector for the various routines in the glue
|
||
; Bits 26-24: Number of bytes of function result for this routine
|
||
; (must be either 0, 2, or 4)
|
||
; Bits 23-16: ID of PDEF to call for high level routines
|
||
; Bits 15-08: The number of bytes of parameters
|
||
; to this routine
|
||
; Bit 07: 1 if the PDEF should be unlocked after
|
||
; the call (high level routines)
|
||
; Bits 06-00: The offset into the PDEF to Jsr to
|
||
; (high level routines)
|
||
; 31 23 15 7 0
|
||
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||
; | | | | | | |
|
||
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||
; | | | | | |
|
||
; | Result Bytes | | Unlock Flag |
|
||
;Routine Selector PDEF ID Parameter Bytes PDEF Offset
|
||
;
|
||
;
|
||
; Routine Selector value
|
||
; ------- -------- -----
|
||
; (high-level routines)
|
||
; PrOpenDoc 0
|
||
; PrCloseDoc 1
|
||
; PrOpenPage 2
|
||
; PrClosePage 3
|
||
; PrintDefault 4
|
||
; PrStlDialog 5
|
||
; PrJobDialog 6
|
||
; PrStlInit 7
|
||
; PrJobInit 8
|
||
; PrDlgMain 9
|
||
; PrValidate 10
|
||
; PrJobMerge 11
|
||
; PrPicFile 12
|
||
; PrHack 13
|
||
; PrGeneral 14
|
||
; (low-level and 'non-link' routines)
|
||
; PrDrvrOpen 16
|
||
; PrDrvrClose 17
|
||
; PrDrvrDCE 18
|
||
; PrDrvrVers 19
|
||
; PrCtlCall 20
|
||
; PrPurge 21
|
||
; PrNoPurge 22
|
||
; PrError 23
|
||
; PrSetError 24
|
||
; PrOpen 25
|
||
; PrClose 26
|
||
;
|
||
|
||
LOAD 'StandardEqu.d'
|
||
INCLUDE 'Printing.a'
|
||
INCLUDE 'PrPrivate.a'
|
||
INCLUDE 'PrintTrapsEqu.a'
|
||
INCLUDE 'Folders.a'
|
||
INCLUDE 'Aliases.a'
|
||
INCLUDE 'LinkedPatchMacros.a'
|
||
|
||
MACHINE MC68020 ; needed for cache flush <LW2> fau
|
||
|
||
;************************************************************************************************
|
||
;* _MDebugStr takes a string for a parameter and calls DebugStr with it.
|
||
;*
|
||
;* Example: _MDebugStr 'In PrOpen'
|
||
;************************************************************************************************
|
||
|
||
MACRO
|
||
_MDebugStr &dbgStr
|
||
|
||
PEA @dbgAddr
|
||
_DebugStr
|
||
BRA.S @pastDbgAddr
|
||
@dbgAddr DC.B &dbgStr
|
||
ALIGN 2
|
||
@pastDbgAddr
|
||
ENDM
|
||
|
||
PrGlue PatchProc $A8FD,(Plus,SE,II,Portable,IIci)
|
||
;
|
||
; A few constants regarding selector values:
|
||
PrDocLimit EQU 3 ; Highest selector for doc loop routine
|
||
PDEFLimit EQU 15 ; Highest selector for high-level (PDEF-calling)
|
||
; routines
|
||
;
|
||
; PrGlue Entry points are below. The idea of this entry setup is to allow PrGlue
|
||
; to determine what entry point was used in very little code space. The Bsr.s
|
||
; pushes the return address on the stack, which PrGlue then uses to derive which
|
||
; entry point was used. The key is that the entry points here are arranged in
|
||
; the same order as the table PrGlueTable, below.
|
||
;
|
||
; Constants: Offsets into the PrGlue information
|
||
Selectr EQU 8+0 ; Selector for routine invoked (Most significant 5 bits)
|
||
FuncByt EQU 8+0 ; Bytes of function result (Least significant 3 bits)
|
||
PDEFId EQU 8+1 ; ID of the PDEF to call (8 bits)
|
||
ParmByt EQU 8+2 ; Bytes of parameters (8 bits)
|
||
CodeOfs EQU 8+3 ; Offset into the PDEF of the code for this function (7 bits)
|
||
;
|
||
; Parameters to the Glue:
|
||
longAt EQU 8 ; Offset from a6 of longWord o'info
|
||
;
|
||
; PrGlue itself
|
||
|
||
Link a6,#0 ; Stack frame, no local variables
|
||
Movem.l a3-a4,-(sp) ; Save the regs we will use to hold info across
|
||
; the call to the actual print routine
|
||
; Get selector in d1
|
||
Moveq #0,d1
|
||
Move.b Selectr(a6),d1 ; Get the byte containing it
|
||
Lsr.b #3,d1 ; Move selector over
|
||
Beq.s OpenDocOnly ; PrOpenDoc has a bunch of special case code, so don't
|
||
; get the ID the way we do it normally
|
||
; If it's a low-level call, dispatch to that stuff
|
||
Tst.b Selectr(a6) ; Test the selector: high-level or low-level?
|
||
Bmi LowLevel ; Send the low-level calls off to thier corner
|
||
; Get Id of PDEF that this call will be dispatched to in d2
|
||
Moveq #0,d2 ; Preset for PDEFId in d2
|
||
Move.b PDEFId(a6),d2 ; Get PDEF Id from Glue Parameter.
|
||
Bne.s GetPDEF ; If that's nonzero, it's the id. If it's zero,
|
||
; the id should be gotten from printing globals
|
||
Moveq #3,d2 ; Mask for PrintLoop type from Globals. This
|
||
; is also the PDEF Id to use
|
||
And.b PrintVars+bDocLoop,d2 ; Get that info into d2
|
||
Bra.s GetPDEF ; ...and go to it
|
||
OpenDocOnly
|
||
; For OpenDoc, we get the print loop type, which is the PDEF Id, from
|
||
; the print record passed by the caller as a parameter.
|
||
Move.l 20(a6),a0 ; Get handle to print record
|
||
Move.l (a0),a0 ; Deref Handle
|
||
Moveq #3,d2 ; Mask for doc loop type
|
||
And.b PrJob+bJDocLoop(a0),d2 ; Mask off them bits
|
||
Andi.b #$FC,PrintVars+bDocLoop ; Clear out those two bits in PrintVars
|
||
Or.b d2,PrintVars+bDocLoop ; and put the new bits in
|
||
;
|
||
; Get that PDEF
|
||
GetPDEF
|
||
Move.w CurMap, a3 ; <22Feb87> JNP save user's resfile refnum in a3
|
||
Clr.l -(sp) ; Room for the GetResource result
|
||
Move.l #'PDEF',-(sp) ; Type
|
||
Move d2,-(sp) ; id
|
||
_GetResource
|
||
Move.l (sp)+,d0
|
||
Tst.l d0 ; Test the result of GetResource
|
||
Bne.s GotPDEF ; we have the PDEF
|
||
|
||
; CurMap may be set to point to the user's res file. We need to set it to point to our resfile.
|
||
; Check the low memory global iPrRefNum. If it is $FFFF (i.e is not used and is initialised)
|
||
; then open the printer resource file to get our refnum. Otherwise use the refnum stored in the
|
||
; low memory global to call _UseResFile. Check the result of this call, if it failed then open
|
||
; the printer resource file to get our ref num.
|
||
|
||
Cmpi.w #$FFFF, iPrRefNum ; is our refnum in low memory?
|
||
Beq.s OpenPrRF ; no, open the printer resource file
|
||
Move.w iPrRefNum, -(sp) ; Try _UseResFile on this refnum
|
||
_UseResFile
|
||
Tst.w ResErr ; Did it work?
|
||
Bne.s GetRsrc ; Yes, so get the PDEF
|
||
OpenPrRF
|
||
MOVE.W D2, -(SP) ; save D2 across the call to FetchDriver
|
||
Bsr FetchDriver ; Open our res file
|
||
MOVE.W (SP)+, D2 ; restore D2 as soon as possible
|
||
Tst.w d0 ; success?
|
||
Beq.s Continue ; <13Feb87> JNP yes, continue
|
||
Move.w d0, PrintVars+iPrErr ; <13Feb87> JNP no, set error and get out.
|
||
Bra GlueAbort ; <13Feb87> JNP
|
||
Continue ; <13Feb87> JNP
|
||
Move.w iPrRefNum, -(sp)
|
||
_UseResFile ; our resfile is opened, now let's use it.
|
||
GetRsrc
|
||
Clr.l -(sp) ; Room for the GetResource result
|
||
Move.l #'PDEF',-(sp) ; Type
|
||
Move d2,-(sp) ; id
|
||
_GetResource ; get that PDEF
|
||
Move.l (sp)+,d0
|
||
Tst.l d0 ; Test the result of GetResource
|
||
Bne.s GotPDEF
|
||
; Can't get the resource... set PrError, and jump down to the return point
|
||
Move.w a3, -(sp) ; User's res file refnum
|
||
_UseResFile ; Restore user's Resource map. Refnum is on the stack.
|
||
Move.w #resNotFound,PrintVars+iPrErr
|
||
Bra GlueAbort
|
||
;
|
||
GotPDEF
|
||
Move.l d0,a4 ; Transfer the handle to an a-reg
|
||
Move.l a4,a0 ; Lock that baby down
|
||
|
||
; Some programmers are pretty slimy and load a PDEF that is empty. They then <LW2> fau
|
||
; stuff some code into it. However, since HLOCK does not flush the cache anymore, <LW2> fau
|
||
; the code that they stuff into it might not get written back to memory. To solve this, <LW2> fau
|
||
; we check here whether the PDEF resource size is less than, say, 32 bytes. If so, we <LW2> fau
|
||
; assume that they have already loaded the PDEF and modified it, so we flush the cache <LW2> fau
|
||
; for them. <LW2> fau
|
||
|
||
_GetHandleSize ; How big is our PDEF Handle <LW2> fau
|
||
cmp.l #32,D0 ; Is it "small" <LW2> fau
|
||
bhi.s @RealPDEF ; no, don't flush the cache <LW2> fau
|
||
jsr ([jCacheFlush]) ; else, flush the caches. <LW2> fau
|
||
@RealPDEF ; <LW2> fau
|
||
_HLock
|
||
;<22Feb87> JNP Restore curMap before jumping into the print code.
|
||
Move.w a3, -(sp) ; <22Feb87> JNP user's resfile refnum
|
||
_UseResFile ; <22Feb87> JNP Restore user's Resource map.
|
||
; Copy the parameters and return value of the routine down onto the stack again
|
||
Lea 12(a6),a0 ; Start of old parameters
|
||
Moveq #7,d0 ; Get bytes of param + bytes of return value in d0
|
||
and.b FuncByt(a6),d0 ; Together, these are the number of bytes to copy
|
||
Add.b ParmByt(a6),d0
|
||
Sub.w d0,sp ; We know the thing isn't actually more than a word wide
|
||
Move.l sp,a1 ; Beginning of destination
|
||
_BlockMove ; Note: Leaves d0 = 0
|
||
; Call the routine. The offset into the PDEF to jump to is given by the glue parameter
|
||
Move.b CodeOfs(a6),d0 ; Get offset (note high part of d0 is still 0)
|
||
Andi.b #$7F,d0 ; Mask off the unlock bit that is stored there
|
||
Move.l (a4),a0 ; Deref PDEF handle
|
||
Jsr 0(a0,d0) ; Call the routine
|
||
; Unlock the PDEF if the unlock bit from PrGlueTable is set
|
||
Move.b CodeOfs(a6),d0 ; The unlock bit is the high-order bit of this byte, so...
|
||
Bpl.s NoUnlock
|
||
Move.l a4,a0
|
||
_HUnlock ; make it float again
|
||
NoUnlock
|
||
Bra GlueOut
|
||
;
|
||
; All the low-level routines are implemented here
|
||
LowLevel
|
||
; Allocate and set up for .Print call a iopb on
|
||
; the stack
|
||
Sub.w #IOQElSize,sp ; Get an iopb
|
||
Lea PrintName,a0 ; Address of .Print string
|
||
Move.l a0,ioFileName(sp) ; Put in iopb
|
||
Move.w #iPrDrvrRef,ioRefNum(sp); Put refNum in iopb
|
||
Clr.b ioPermssn(sp) ; Always a good idea
|
||
Move.l sp,a0 ; Put pointer in a0
|
||
; The selector is in d1. We're gonna do a jump table on
|
||
; it. After the jump table, everybody should branch
|
||
; back to LLOut.
|
||
Moveq #0,d0 ; Since LLOut uses d0 as a return code,
|
||
; let's make sure it's something reasonable
|
||
Bclr #4,d1 ; We don't want the high bit
|
||
Add.w d1,d1 ; Shift selector left one
|
||
Move.w LLJump(d1),d1 ; Get jump table entry
|
||
Jmp LLJump(d1) ; Go to correct entry
|
||
LLJump
|
||
DC.W DrvrPrOpen-LLJump ; PrDrvrOpen 16
|
||
DC.W DrvrPrClose-LLJump ; PrDrvrClose 17
|
||
DC.W DrvrDCE-LLJump ; PrDrvrDCE 18
|
||
DC.W DrvrVers-LLJump ; PrDrvrVers 19
|
||
DC.W CtlCall-LLJump ; PrCtlCall 20
|
||
DC.W PurgePr-LLJump ; PrPurge 21
|
||
DC.W NoPurgePr-LLJump ; PrNoPurge 22
|
||
DC.W GetError-LLJump ; PrError 23
|
||
DC.W SetError-LLJump ; PrSetError 24
|
||
DC.W PrintOpen-LLJump ; PrOpen 25
|
||
DC.W PrintClose-LLJump ; PrClose 26
|
||
DC.W LoadDriver-LLJump ; Load Driver 27
|
||
DC.W LLBadParam-LLJump ; not implemented 28
|
||
DC.W LLBadParam-LLJump ; not implemented 29
|
||
DC.W LLBadParam-LLJump ; not implemented 30
|
||
DC.W LLBadParam-LLJump ; not implemented 31
|
||
LLBadParam
|
||
Move.w #paramErr,PrintVars+iPrErr ; Yes, say params in error
|
||
GlueAbort
|
||
Moveq #0,d1 ; Get the number of bytes of parameter to this entry in d1
|
||
Move.b ParmByt(a6),d1 ; Get from the glue parameter, source of all knowledge...
|
||
Bra PrExit
|
||
|
||
LoadDriver
|
||
BSR FetchDriver ; error in D0
|
||
|
||
; LLOut is the exit point for this routine. It takes the error in D0 and sets
|
||
; iPrErr with it. We only want that to happen under two circumstances:
|
||
; [1] when the error is uninitialized and
|
||
; [2] when the error is noErr.
|
||
; If the error is already set, we want to leave it alone. This code manages
|
||
; that change. <11>
|
||
|
||
MOVE.W PrintVars+iPrErr, D1 ; get the error in D1 (faster than low-mem access)
|
||
CMPI.W #-1, D1 ; is error uninitialized?
|
||
BEQ LLOut ; Yes, use D0 to set it.
|
||
|
||
TST.W D1 ; Otherwise, is an error pending?
|
||
BZ LLOut ; no, so set the error from D0 in LLOut
|
||
MOVE.W D1, D0 ; otherwise, refresh the D0 error for exit
|
||
BRA LLOut ; LLOut will therefore not reset the error.
|
||
|
||
PrintOpen
|
||
_PrDrvrOpen ; Open the .Print driver
|
||
Move.w PrintVars+iPrErr, d0 ; <22Feb87> JNP Move the error into d0
|
||
BNE.S PrOCerr ;abort if error.
|
||
ST -(SP) ;Mark call "open", by setting a byte true on stack (NB, 3/23/90)
|
||
BRA.S PrOCcom
|
||
PrintClose
|
||
;<13Feb87> JNP removed call to _PrDrvrClose
|
||
; DON'T check for an answer ; just keep slogging through
|
||
SF -(SP) ;Mark Call "close" by setting stack byte false. <NB: 3/23/90>
|
||
PrOCcom
|
||
Bsr FetchDriver ; Open the printer resource file, error in D0
|
||
MOVE.B (SP)+, D1 ; get the flag byte in D1. Always clean up stack!
|
||
|
||
Tst.w D0
|
||
Bne.s PrOCerr ; Error! get out
|
||
; Test result of OpenResFile
|
||
Move.w iPrRefNum, d0 ; get the refnum in d0
|
||
Tst.w ResErr
|
||
Bne.s @26
|
||
;Now return for opens, or close the resfile with the id
|
||
;found above if closing.
|
||
TST.B D1 ;Open Call?
|
||
BNZ.S @26 ;Yes: Go home
|
||
MOVE.W D0,-(SP) ;No: CloseResFile. Push the refnum param
|
||
_CloseResFile
|
||
@26
|
||
Move.w ResErr,d0
|
||
PrOCerr
|
||
Bra LLOut
|
||
DrvrPrOpen
|
||
CLR.W PrintVars+iPrErr ; force error to noErr at startup for a clean beginning
|
||
_Open ; Do the open
|
||
Bra.s LLOut ; and out
|
||
DrvrPrClose
|
||
_Close ; Do the close
|
||
Bra.s LLOut ; and out
|
||
DrvrDCE ;
|
||
Bsr.s GetDCEHandle ; Get DCE handle in a0
|
||
add.w #IOQELSize-4, sp ; Leave room for the DCEHandle
|
||
Move.l a0, (sp) ; Move the handle to the stack,
|
||
; Glueout will pick up the value and adjust the stack
|
||
Bra.s GlueOut ; get out
|
||
DrvrVers ;
|
||
Bsr.s GetDCEHandle ; Get DCE handle in a0
|
||
Move.l (a0),a0 ; Deref it
|
||
Moveq #0, d0
|
||
Move.b DCtlQueue+1(a0),d0 ; Get the version byte
|
||
add.w #IOQELSize-2, sp ; Leave room for one word
|
||
Move.w d0, (sp) ; Move the version# to the stack,
|
||
; Glueout will pick up the value and adjust the stack
|
||
Bra.s GlueOut ; Get out
|
||
CtlCall
|
||
Move.l 12(a6),csParam+8(a0) ; lParam3
|
||
Move.l 16(a6),CSParam+4(A0) ; lParam2
|
||
Move.l 20(a6),CSParam(A0) ; lParam1
|
||
Move.w 24(a6),CSCode(A0) ; iWhichCtl
|
||
_Control
|
||
Bra.s LLOut ; and out
|
||
PurgePr
|
||
Bsr.s GetDCEHandle ; Get DCE handle in a0
|
||
Move.l (a0),a0 ; Deref DCE handle
|
||
Btst #dRAMBased,dCtlFlags+1(a0); Is this a RAM-based driver?
|
||
Beq.s LLOut ; No? Well then it's not gonna purge
|
||
Move.l DCtlDriver(a0),a0 ; Get driver handle
|
||
_HPurge ; make purgeable
|
||
Bra.s LLOut
|
||
NoPurgePr
|
||
Bsr.s GetDCEHandle ; Get DCE handle in a0
|
||
Move.l (a0),a0 ; Deref DCE handle
|
||
Btst #dRAMBased,dCtlFlags+1(a0); Is this a RAM-based driver?
|
||
Beq.s LLOut ; No? Well then it's won't purge anyway
|
||
Move.l DCtlDriver(a0),a0 ; Get driver handle
|
||
_HNoPurge ; make non purgeable
|
||
Bra.s LLOut
|
||
GetDCEHandle
|
||
Move.w #1,csCode(a0) ; The old get-the-DCE status call
|
||
_Status
|
||
Move.l csParam(a0),a0 ; Get DCE Handle
|
||
Rts
|
||
GetError
|
||
add.w #IOQElSize-2,sp ; Strip parameter block except for one word
|
||
Move.w PrintVars+iPrErr,(sp) ; Get error code
|
||
Bra.s GlueOut
|
||
SetError
|
||
Move.w 12(a6),d0 ; Set the error code in register
|
||
;
|
||
; LLOut: All the low-level routines return here, with
|
||
; their error code in d0.
|
||
LLOut
|
||
Add.w #IOQElSize,sp ; Strip parameter block
|
||
Move.w d0,PrintVars+iPrErr ; Set return code
|
||
GlueOut
|
||
;
|
||
; Get the number of bytes of parameter to this entry in d1
|
||
Moveq #0,d1
|
||
Move.b ParmByt(a6),d1 ; Get from the table, source of all knowledge...
|
||
; Copy the function value, if any, back up to the caller's stack frame
|
||
Moveq #7,d0 ; We're going for # bytes function value in d0
|
||
and.b FuncByt(a6),d0 ; Got 'em
|
||
Beq.s NoRetVal
|
||
Move.l sp,a0 ; The function left its result on top of stack
|
||
Lea 12(a6,d1),a1 ; The place we want to go is after the original params
|
||
Lsr.w #1, d0 ; <13Feb87> JNP
|
||
Bra.s @1 ; <13Feb87> JNP
|
||
@2 Move.w (sp)+, (a1)+ ; <13Feb87> JNP
|
||
@1 Dbf d0, @2 ; <13Feb87> JNP
|
||
NoRetVal
|
||
Move.w PrintVars+iPrErr, d0 ; Leave function result in D0 <12> NB
|
||
PrExit
|
||
;
|
||
; Unwind our stack frame and strip the params (# bytes params still in d1)
|
||
Movem.l (sp)+,a3-a4
|
||
Unlk a6
|
||
Move.l (sp)+,a0 ; Return address
|
||
Adda.l d1,sp ; Strip params
|
||
Addq #4,sp ; Strip glue parameter
|
||
Jmp (a0) ; ...and we're out
|
||
;
|
||
; Subroutines for PrGlue
|
||
;
|
||
|
||
kStartupDisk EQU -1
|
||
|
||
;************************************************************************
|
||
; FindSpecialFolder - find the dirID of a special folder
|
||
; <12jan90 fjs, 3/22/90 used a stack frame: nb>
|
||
;
|
||
; in: d0 = foldertype (ie 'extn')
|
||
; out: d0 = dirID (or 0 if an error occurred) ( this is a lie --sad & ich )
|
||
;************************************************************************
|
||
|
||
FSFStackFrame RECORD 0,decr
|
||
|
||
vRefNum DS.W 1
|
||
dirID DS.L 1
|
||
|
||
kFSFSize EQU *
|
||
ENDR
|
||
|
||
FindSpecialFolder
|
||
WITH FSFStackFrame
|
||
LINK A6, #kFSFSize
|
||
SUBQ.W #2, SP ; space for error
|
||
MOVE.W #kStartupDisk, -(SP) ; this volume
|
||
MOVE.L D0, -(SP) ; folder type (input)
|
||
SF -(SP) ; don't create
|
||
PEA vRefNum(A6) ; ptr to the output vRefNum
|
||
PEA dirID(A6) ; ptr to output dirID
|
||
_FindFolder
|
||
MOVE.W (SP)+, D0 ; fetch error
|
||
BNZ.S @bail ; oh, well. Unlink and out.
|
||
|
||
MOVE.L dirID(A6), D0 ; if no error, copy dirID into output reg.
|
||
|
||
@bail UNLK A6
|
||
RTS
|
||
ENDWITH
|
||
|
||
;************************************************************************
|
||
; FetchDriver: open the system printer's resource file:
|
||
; We do this by resolving the alias written into the system file by
|
||
; the chooser. This alias maps from the system file to the driver.
|
||
; We canonify the system file, and then call ResolveAlias to create
|
||
; a canonified representation of the driver. That representation
|
||
; contains the information needed by HOpenResFile, which we then call.
|
||
; Any error is returned in D0.
|
||
;************************************************************************
|
||
|
||
FetchDriver
|
||
|
||
;************************************************************************
|
||
; CanonSysFile: Canonify the system file
|
||
;
|
||
; sysFileCanon(A6) contains the output CanonSpec if the routine succeeds.
|
||
; If an error occurs, the entire routine is abandoned, with the error in D0.
|
||
;
|
||
; pascal OSErr CanonifyFile(short vRefNum,
|
||
; long dirID,
|
||
; const Str255 *fileName,
|
||
; CanonicalFileSpec *canonicalFile);
|
||
;************************************************************************
|
||
|
||
SpecRec RECORD 0,decr
|
||
|
||
sysFileSpec DS.B FSSpec.size
|
||
driverSpec DS.B FSSpec.size
|
||
aliasHandle DS.L 1
|
||
wasChanged DS.B 1
|
||
if theFuture then ; PURGEALIAS
|
||
aliasState DS.B 1 ; State of the alias
|
||
endif ; PURGEALIAS
|
||
|
||
ALIGN 2
|
||
|
||
kSpecSize EQU * - SpecRec
|
||
ENDR
|
||
|
||
|
||
kAliasID EQU -8192 ; System Printer alias's resID
|
||
|
||
WITH SpecRec
|
||
|
||
LINK A6, #kSpecSize
|
||
|
||
MOVE.L #kSystemFolderType, D0 ; get this folder's dirID
|
||
BSR.S FindSpecialFolder ; if cond code < 0, then we have an error
|
||
BMI @Bail ; if failure, exit routine, error in D0
|
||
|
||
; create a file spec for the system file
|
||
|
||
MOVE.W #kStartupDisk, sysFileSpec + FSSpec.vRefNum(A6) ; VRefNum of startup disk
|
||
MOVE.L D0, sysFileSpec + FSSpec.parID(A6) ; dirID from FetchSpecialFolder
|
||
|
||
MOVEQ #0, D0 ; clear out D0 for BlockMove
|
||
LEA SysResName, A0 ; Copy system file's name
|
||
MOVE.B (A0), D0 ; which is this long
|
||
ADDQ.B #1, D0 ; plus that length byte!
|
||
LEA sysFileSpec + FSSpec.name(A6), A1 ; to the FSSpec
|
||
_BlockMove
|
||
|
||
; ResolveDriver: Resolve the alias using the system file's FSSpec.
|
||
|
||
SUBQ #4, SP ; allocate space for GetResource
|
||
MOVE.L #rAliasType, -(SP) ; get this type
|
||
MOVE.W #kAliasID, -(SP) ; get this ID
|
||
_GetResource ; fetch, boy!
|
||
MOVE.L (SP)+, D0 ; this is the handle
|
||
MOVE.L D0, aliasHandle(A6) ; save it across all these calls
|
||
BNZ.S @ResolveIt ; got one. Off we go...
|
||
|
||
; This is a new problem for the glue. If the resource for the alias is not found, then
|
||
; we would normally return resNotFound. The glue used to return fnfErr whenever it couldn't
|
||
; open the driver and applications have coded for that error. Rather than add an error
|
||
; code, we map resNotFound to fnfErr and save the user some grief.
|
||
|
||
@failedGetRes
|
||
MOVE.W ResErr, D0 ; copy error into output var
|
||
BNZ.S @Bail ; and exit if non-zero
|
||
MOVE.W #fnfErr, D0 ; else, return fnfErr so apps alert the user correctly
|
||
BRA.S @Bail ; and exit.
|
||
|
||
@ResolveIt
|
||
if theFuture then ; PURGEALIAS
|
||
Move.l aliasHandle(A6),A0
|
||
_HGetState
|
||
Move.b D0,aliasState(A6) ; Save the Alias state.
|
||
_HNoPurge ; Make the alias non-purgeable
|
||
endif ; PURGEALIAS
|
||
|
||
SUBQ.W #2, SP ; space for error
|
||
PEA sysFileSpec(A6) ; first parameter
|
||
MOVE.L D0, -(SP) ; the alias handle
|
||
PEA driverSpec(A6) ; ptr to driverSpec
|
||
PEA wasChanged(A6) ; ptr to output boolean (ignored)
|
||
_ResolveAlias
|
||
MOVE.W (SP)+, D0 ; got the error here.
|
||
BNZ.S @Cleanup
|
||
|
||
TST.B wasChanged(A6) ; check if the alias needs updating
|
||
BZ.S @CallHOpenRes ; Nope, keep going
|
||
|
||
MOVE.L aliasHandle(A6), -(SP) ; Now set the resource changed
|
||
_ChangedResource
|
||
TST.W ResErr
|
||
BNZ.S @Cleanup ; exit on error
|
||
|
||
CLR.W -(SP) ; Update the system file
|
||
_UpdateResFile ; (refnum = 0)
|
||
TST.W ResErr
|
||
BNZ.S @Cleanup ; exit on error
|
||
|
||
@CallHOpenRes
|
||
SUBQ.W #2, SP ; space for function result
|
||
MOVE.W driverSpec + FSSpec.vRefNum(A6), -(SP) ; parameter 1: vRefNum
|
||
MOVE.L driverSpec + FSSpec.parID(A6), -(SP) ; parameter 2: parent ID
|
||
PEA driverSpec + FSSpec.name(A6) ; parameter 3: ptr to fileName
|
||
MOVE.B #fsCurPerm, -(SP) ; set permission to "current"
|
||
_HOpenResFile
|
||
|
||
MOVE.W (SP)+, D0 ; grab function result
|
||
|
||
MOVE.W D0, iPrRefNum ; If it worked, then set the refnum
|
||
MOVE.W ResErr, d0 ; set the error in D0
|
||
|
||
@Cleanup
|
||
|
||
if theFuture then ; PURGEALIAS
|
||
Move.l aliasHandle(A6),A0
|
||
Move.b aliasState(A6),D0 ; Restore the alias state.
|
||
_HSetState
|
||
endif
|
||
MOVE.L aliasHandle(A6), -(SP) ; release the alias resource
|
||
_ReleaseResource
|
||
|
||
@Bail UNLK A6 ; error in D0.
|
||
RTS
|
||
ENDWITH
|
||
|
||
; Name of the .Print driver
|
||
|
||
STRING PASCAL
|
||
PrintName DC.B '.Print'
|
||
ALIGN
|
||
|
||
ENDPROC
|
||
|
||
|
||
END
|
||
|
||
|
||
|