; ; File: ResourceMgr.a ; ; Written by: Bruce Horn 22nov82 to 10sep83 ; ; Copyright: © 1988-1993 by Apple Computer, Inc. All rights reserved. ; ; Change History (most recent first): ; ; 11/7/93 SAM Roll in from mc900ftjesus. ; 11/7/93 SAM Fixed a couple of calls to GetMap/GetSysMap in vRMgrStdEntry ; that were checking A4 as the function result, which is wrong and ; will never indicate failure. Removed a couple of redundant loads ; of ExpandMemPtr (tons of room for improvement here...). ; 10/27/93 rab Backed out change SM45. It fixed the bug, but caused a ; significant loss of performance (Å3x). ; 9/16/93 SAM In RsrcZoneInit, check for the zonePtr = bufPtr before calling ; _TrashZone. The boot process calls _InitApplZone w/ApplZone = ; bufPtr as a bogus zone. The heap utils assumes the zone passed ; to it is a zone (duh!). ; 9/13/93 SAM Added a call to _TrashZone (HeapUtils) to the start of ; RsrcZoneInit. ; 6/22/93 kc Roll in bug fix from Ludwig. ; 6/17/93 mal (kc) Fixed NameUsedByOthers to save A2 then restore into A3. ; 6/6/93 BT Roll in the process manager patch on GetResource under the ; conditional compile flag 'hasRISCV0ResMgrPatches'. This is for ; speed so we don't hit mixed mode so often. Compatibility with ; old process manager is maintained, this is patch is an app ; anachronism. ; 5/30/93 SAM Replaced several _Get/SetZone to MOVE.L A0,TheZone (etc). ; 5/27/93 SAM Reintroduced the "is this resource from the system" check in ; checkload. Moved the definition of mapForceSysHeap into ; ResMgrPriv.a equate file. ; 5/21/93 CSS Remove FixSMgrWorld import per P. Edberg review. Plus change ; $Axxx to _PrGlue per Cyclone review. ; 5/14/93 PN Take out the check load roll in from ProcessMgr because we are ; now still using the old ProcessMgr therefore it applies the ; check load fix twice. ; 4/28/93 CSS Fix Radar bugs #1079158. RmveResource had several problems: It ; was not reporting errors correctly and the check for the sysmap ; against the curmap should have been for the system override map. ; Also, in FlushResourceCache clear the expandmem ; emLastMapOverridden before the check if emResourceCache is clear ; because sometimes these two aren't set up together. If we call ; FlushResourceCache, emLastMapOverriden must be cleared. ; 4/26/93 CSS Fix comment for . ; 4/26/93 CSS UseResFile doesn't work right with overrides. Because it calls ; StdTwoExit (which restores the curmap if overrides are enabled). ; Fix UseResFile to clear local override flag so that we don't write ; over curmap after we just changed it. ; 4/16/93 kc Add AddNewRefWithoutUpdate entrypoint to AddNewRef so that ; MakeOverrideMap doesn't set the mapChanged bit. Add code to cach ; the override map refnum so that resedit doesn't corrupt the ; system file. This fixes #1069183. ; 4/9/93 CSS Change scratch register from D0 to A0 because Eric A. did it ; that way in the shipping products. ; 4/8/93 CSS Rollin fix to UpdateResFile to allow it to work correctly in ; multithreaded environment. (from Eric Anderson). Radar bug ; #1077394. ; 3/24/93 CSS Try _FlushFile after SetRFEof calls to hopefully fix the various ; -39 bugs (eof errors). Add the utility RFFlush which will ; acomplish the flush. Changed a short branch to word branch. ; 3/22/93 CSS Code to restrict the Uniqueid fuction to 128-32767 was checking ; against d0 which is how it was in the patch, but in this context ; is incorrect. In the patch d0 was pulled off the stack. In the ; current code the candidate unique id is in d2. So, I changed ; the code to reflect this. This fixes Radar bug #1063282, and ; #1062580. ; 3/19/93 CSS In LoadResource, clear ResErr if the resource is in ROM so ; Hypercard doesn't blow its brains out when in sees lint in ; ResErr after trying to load a WDEF (which is in ROM). ; 3/16/93 GMR Fixed the PRAM combo validity check- changed BLE.S to BLS.S to ; properly handle $80-$FF values. ; 3/2/93 PN The rGetResource patch is only for a specific case when it ; looking for 'mitq' resource and it should not be rolled into ; ROM. So I back out the change. ; 3/2/93 PN Fix the previous change to set current map before calling ; GetResource according to DY. ; 2/26/93 PN Roll in a patch StartRGetResourceSearchFromTopOfResourceChain to ; rGetResource ; 2/26/93 BT Change call in GetIndResource to call CheckLoad, not jump ; through it's vector. This breaks FlashPort and doesn't buy ; anything. ; 2/5/93 PN Roll in a_checkload proc from ProcessMgrMisc.a into CheckLoad ; 1/28/93 PN Fix comment to call PrGlue ; 1/11/93 PN Fix Radar# 1059658. The AppleTalk ImageWriter and LQ AppleTalk ; ImageWriter are not 32bit clean. They set the high bit in master ; pointer block to lock the handle. Until that bug is fixed in the ; drivers. This code is used to fixed that problem and is put into ; OpenResFile. ; 12/16/92 PN Fix LoadResource to handle NILHandle correctly ; 12/10/92 PN Radar# 1051364 Fix LoadResource to check for purged resource and ; nil handle before doing HandleScan. ; 12/4/92 RB In DetachResource and ReleaseResource, do not dispose of the ; handle to resources that are in ROM in the Override Map used for ; system overrides. ; 12/4/92 SWC Moved InitRSRCMgr here from StartInit.a. ; 12/1/92 RB Removed the GetResource hack since we have figured out a better ; way. ; 11/20/92 RB Fixed a scrw-up in the last chekin, it'll the code will not ; really do what I wanted. ; 11/20/92 RB In GetResource, if the type is WDEF or MDEF try looking in ROM ; first, because the Process Manager is not looking in ROM. I know ; this is gross, but it's not like it has not been done before. ; 11/11/92 BT Add dummy entry points that FlashPort will use to attach hints ; to. Use of routine entry point was not sufficient to maintain ; offset integrity when source changes move code that is being ; hinted. ; 11/10/92 RB Renamed CheckGrow@1 to CheckGrowAt1, since Flashport don't like ; it. ; 10/22/92 CSS Change some branch short instructions to word branches. ; 9/28/92 PN Take out the unneccessary save A0 and A1 around GetOverrideMap ; calls ; 9/25/92 PN #1042784 Fix AddResource and UpdateResFile to flush the ; ResourceCache and also set the mapChanged bit in the map that is ; overridden to ensure that the override map is updated when the ; original resource map is updated. ; 9/17/92 kc Change Bsr to BigJsr. ; 9/9/92 kc Fix bug in SizeResource that was corrupting TeachText. ; 9/8/92 PN Radar#1041949. Fixed the problem in UpdateResFile where it ; should return ResFNotFound when an invalid refnum being passed ; in. ; 8/28/92 kc Fix bug in SizeRsrc. ; 8/12/92 PN Temporary fix the LoadResource call so that if a handle of a ; resource in ROM is passed in it will do nothing, otherwise it ; will load the resource as always. ; 8/6/92 PN FM. Fixed the last check in so that it does not destroy chooser ; resource. It is working now, more work is still needed. ; 8/6/92 FM Fixed bug in UpdateResFile. Needed to turn off resource ; overrides when calliing stdentry. Also need to set up a2/a3 ; when calling updateresfilecommon. ; 7/27/92 FM Fix mistake in AddResource, where I wasn't preserving ; emScanOverrides correctly! ; 7/27/92 FM Roll in the ResourceOverrides code from reality. ; Here are the many changes I have made to the resource manager: ; ; - Fixed LoadResource. Call HandleScan BEFORE checking for purged handle or else NIL and non-resource ; handles can mess us up!É ; ; - put installproc to turn on resource overrides in InitResources(). Makes more sense here ; than in the startinit time stuffÉ ; ; - Changed permission byte and DirID handling for the OpenResFile suite of calls ; (HOpenResFile, OpenResFile, OpenRMgrPerm and CreateResFile as well). The old-style default values are ; set up in StdEntry. HFS aware calls then fill in the ioBlock in the Resource ; Managers stack frame as needed. ; This should fix some of the QuickTime 1.1 problems we were havingÉ ; ; - Removed the DirID being passed into NewMap. ; ; - Made HOpenResFile, OpenRFPerm and OpenResFile share common code in ; OpResFile common. ; ; - Added SetFileIODirID as a companion to SetFileIO since ioPosOffset and the ioDirID ; collide in a paramblock. ; ; - Changed NewMap to clear overrideBits when creating NewMaps, in case they ; were written out to disk. ; ; - Optimized the code to get often used OverrideSysMapHndl from the ResourceMgr ; stack instead of calling GetOverrideMap.The stack is set up in StdEntry. ; RsrcZoneInit now does this for example. ; ; - RsrcZoneInit no longer checks the systemmHeapBit when determining which resources to ; purge. Instead in checks the location of the resource handle to determine if it should ; be in the system heap or not. ; ; - Changed CloseAllFiles to use the OverrideSyMapHndl stack value instead ; of calling GetOverrideMap. ; ; - Got rid of ORFCommonHFS entry point since it is no longer needed. ; DirID is now set up on entry to an openrefile call. Now use OverrideSysMap to ; get string $E000 when checking for opens to the .Print driver. That way overrides ; will work correctly for this string resource. ; ; - Special cased UseResFile when the user passes in 0. This is because unlike all other calls ; using resource overrides, we want UseResFile to set to the SystemMap in this case and not ; override of the SystemMap which is what StdMapEntry would do. (Actually UseResFile has ; been defined to not respect override maps in any case, not just the case of the system map.) ; This makes some sense since when we set CurMap to equal SysMap, most ResourceMgr calls ; will end up using the System Override map anyways. This is because StdEntry will set up ; CurMap to be the override map on entry. ; ; ; - Made lots of changes to UpdateResFile to reflect the use of override maps. ; ; - Check to see if weÕre updating the system file, or just another file. If weÕre updating the ; system file, then make sure we update all the font files too. If itÕs just a generic resource map, ; update just itÕs override maps and the file itself. ; ; - from DTY-> ; Note: I know that explicitly updating an override map of the system wonÕt update the ; font files. I think this is the right behaviour, since anyone that is referencing ; the override map explicitly probably has something specific in mind. ; ; - Changed CloseResFile to respect the override bit preventFileFromBeingClosedBit. Also ; added a call to CheckAndFlushFontCache which will flush the font cache if we are closing ; a file that contains 'FOND's or 'FONT's. ; ; ; - Completely rewrote Count(1)Resources to use Deans new Resource caching code. His caching ; code is smart enough to predict that someone doing a CountResources will soon be doing ; a GetIndResource. Since the results of the CountResources are cached, the GetIndResource ; calls should be much faster.p ; ; ; - Completely rewrote GetIndResource to use the new caching code. I'm not sure that ; the RMgrPerm -> ioBlock+ioPermssn(a6) is necessary but thats how Dean wrote it. I'll ; check it out with him tomorrow. ; ; - Changed Get(Cur)Map to use the OverrideSysMap instead of SysMap. ; ; - Changed NextMap to work correctly with override maps in the OneDeep case. It used to ; be that NextMap would bail when ResOneDeep was set. Now if the map has the overrideNextMap ; or twoDeepBit set then we try the next map even in OneDeep mode. ; ; - Reworked StdEntry to iomplement ResourceOverrides and HFS Aware ResourceMgr calls. ; StdEntry now seth the ioBlock to its default values. It sets up CurMap to reflect ; any override maps that exist for the old CurMap. (CurMap is restored to its previous value ; in StdExit.) I also save of the OverrideSysMapHndl and OverrideSysMap since they are ; so frequently used. After all of this is done if RomMapInsert is true StdEntry calls ; the rewritten SwapRomMap. ; ; - Rewrote SwapRomMap to respect the SystemOverrideMap. ; Now that we have overrides, we want to put the ROM map at the ; very end of the resource chain when swapping it out ; and we want to put it in front of any system override maps ; ; - Rewrote StdExit to restore all the changes necessary to make resource overrides work. ; ; - Added code to CheckLoad to set the DeanBit when loading a resource and to clear the ; Dean bit if the handle already exists. That way people can tell if they caused a resource ; to be loaded or not. ; ; - Added a new utility routine called UpdateOverriddenChangedBits. This marks the changed bits ; for any files overriden by the map in A4. This is called anywhere that the ResourceMgr ; sets MCCMask or mapChanged on a map. ; ; - Rewrote FlushChangedFonds to be register based because it is more efficient ; and because it allows us to easily call it after StdEntry which fits better with the ; existing architecture(?) of the ResourceMgr. ; ; - WriteResource now flushes the resource cache. ; ; - rolled in Phillips fix for DiskCachePurge ; 7/10/92 PN Fix a bug in RPHook that cause the call to crash on rts. Put the ; handle on the stack again before jsr DiskCachPurgeProc ; ; ; - In AddResource Got rid of FlushChangedFONDsForAdd. I call the new register ; based FlushChangedFonds now. ; ; Also change AddResource to turn off emScanOverrides before calling StdZEntry. ; This is because AddResource is one of the few cases where we actually ; don't want to use an override map. (UseResFile is another example!) ; ; - RmveResource is documented to only allow you to remove a resource ; when it's homeresfile is in CurMap. With overrides we want to modify ; this behavior slightly to allow RmveResource calls from CurMap ; and any files that are overridden by CurMap. ; ; We also special case to allow Rmve's from system files that are below the system when ; the CurMap == SysMap. (e.g. Font Files) ; ; New Routines Added---> ; ; - New routine CacheResource from ResourceMgrExtensions.a. Made a few changes to ; work outside of its previous patch environment. ; ; - IsDuplicate - utility routine called by CacheResource. Determines whether a resource ; and ID have already been cached or not. This is how we prevent duplicates from appearing ; for maps with the dontCountOrIndexDuplicates bit. ; ; - DoesCachedMapOverrideCurrentMap - utility routine called by CacheResource. Given two ; resource map handles, this routine determines if one is an override map of the other. ; This is done by traversing the resource chain from the second resource map until a map ; is found that does not have the overrideNextMap bit set. If any of the resource maps ; that are visited during the traversal match the first resource map parameter, this routine ; returns that the current map is overriden by the cached map. ; ; - CheckAndFlushFontCache - Called By: OpenResFile, HOpenResFile, OpenRFPerm, CloseResFile. ; If the map being opened or closed contains 'FONT' or 'FOND' resource we invalidate ; the font caches. ; ; - FindOverriddenMap- Given a handle to a resource override map, find the map it overrides. ; This routine assumes that the map passed in is an override map. ; ; - FlushResourceCache - disposes the resource cache handle to force the cache to ; be rebuilt next time _CountResources or _GetIndResource is called. The cache ; will be flushed whenever the offset to a resource stored in the cache may become ; invalid (when resources are added or removed from the map or when the map is updated or ; written to disk) and when files are opened or closed which may cause the count to ; become invalid. ; ; ; 7/10/92 PN Fix a bug in RPHook that cause the call to crash on rts. Put the ; handle on the stack again before jsr DiskCachPurgeProc ; 6/12/92 CSS Roll-in Reality Changes: ; <12> 6/11/92 FM Remove obsolete call to FixSMgrWorld. ; 6/3/92 PN Fix the HCreateResFile to get the dirID and VRefNum correctly. ; 6/3/92 CSS Integrate patch to RsrcZoneInit. Fix to CloseFiles to not close the override files that override ; the system resources. This is based on a patch to RsrcZoneInit ; that changes SysMapHndl to fake out closefiles to effectively do ; the same thin. ; 5/7/92 stb roll in TrueType patch on SetResPurge for disk-based font caches ; (from DiskCachePatches.a). Rewrote to no longer need the ; TrueType global reference to the resource mgr purge proc, ; although the TrueType routine is still in place for RAM ; versions. ; 4/24/92 PN Roll in NewCreate and NewOpenRF ValidatefileSizeInCheckGrow/ ; OpenDirIDResfile/ ; OpenRFPermDirIDExit/OpenresfileDirIDExit/CreateDirIDresfile/Crea ; teresfileDirIDExit from ResourceMgrExtensions.a ; 4/18/92 kc Fix bug in GetIndResource. (Change TST.L to TST.W) ; 4/14/92 stb Add the comments I so conveniently forgot to addÉ ; 4/14/92 stb remove the ŌscodÕ patch on GetResource. Roll in decompression ; patches. ; <5> 3/11/92 stb fix GetIndResource and Get1IxResource so the result gets cleared ; BEFORE bailing out if the index was bogus. Flush 'FOND' candidate ; lists in AddResource, RmveResource, and ChangedResource. ; unroll <10> 'scod' patch on GetResource. Whoops, not yet. ; <4> 2/26/92 stb roll in patches for LoadResource, AddResource, GetIndResource, ; UniqueID. Fix ROZ map handle size bug in CountCombos where ; unnamed resources caused 255 bytes extra to be allocated in the ; map handle. Removed obsolete (conditionalized out) code in ; ORFCommon. ; <12> 2/14/92 stb remove support for ignored resources (conditional: hasResIgnored) ; <11> 2/14/92 stb roll in fix to RmveName so that a name doesnÕt get removed if it ; is in use by any other resource. This seems odd, but files like ; this exist, and we want them to work. ; <10> 1/20/92 PN Roll in the linkedpatch from segmentloaderpatches.a to force ; loading 'scod' resource ; <9> 1/8/92 RB Exported a few symbols so that the LinkedPatches for ; ResourceMgrExtensions can be used from ROM. ; <8> 6/12/91 LN changed #include 'HardwareEqu.a' to 'HardwarePrivateEqu.a' ; <7> 9/13/90 BG The unnamed author referred to in <6> is helping simplify things ; by removing code added for -eclipseDebug- because it is no ; longer necessary with the latest rev. of the 040. In general, ; mods <4> and <5> were removed. ; <6> 9/12/90 MSH &SWC: Fixed a bug in some eclipseDebug code in NameResource. The ; code was replacing an ADDA.W offset(Ax),Ax instruction with ; several instructions. However, the author of the replacement ; code didn't realize that that particular ADDA also does a sign ; extend of what's at offset(Ax) before, doing the add, and his ; code didn't. Very messy if the addition happens to occur with ; particular values. ; <5> 8/6/90 BG Some more EclipseNOPs were needed. ; <4> 7/17/90 BG Added EclipseNOPs for flakey 040s. ; <3> 6/27/90 CCH Fixed bug in CountCombos that increased size of ROM rsrc map by ; 255 bytes for each ROM rsrc without a name. Also removed code ; for non-combo ROM resources. ; <2> 2/1/90 CV Checking for an FPU based on the combo and HWCfgFlags. If the ; FPU is present, the combo is changed to 3 which uses the FPU ; SANE package rather than the non-FPU SANE. ; <1.6> 11/8/89 BPA Added support for ignored resources (conditional: hasResIgnored) ; <1.5> 10/2/89 BPA Catenated source files RmgrAsm1.a, RmgrAsm2.a and RmgrAsm3.a ; source files to this file. ; <1.4> 8/30/89 dba moved common equates for ResourceMgrPriv.a ; <1.3> 6/30/89 GGD NEEDED FOR AURORA: Added include of HardwareEqu.a, ; UniversalEqu.a, deleted Nequ.d ; <1.2> 6/29/89 BBM Added vectors for vRMgrStdEntry and vRMgrStdExit in RMgrAsm2.a ; <1.1> 11/10/88 CCH Fixed Header. ; <1.0> 11/9/88 CCH Adding to EASE. ; <„1.1> 9/23/88 CCH Got rid of inc.sum.d and empty nFiles ; <1.0> 2/11/88 BBM Adding file for the first time into EASEÉ ;______ EASE Modification History for file RmgrAsm1.a ____________________________________ ; <1.9> 8/30/89 dba changed MapReadError to mapReadErr ; <1.8> 7/6/89 PKE NEEDED FOR AURORA & ESPRIT: Fixed Script Mgr initialization in ; InitResources to work properly for switch launch. ; <1.7> 6/30/89 CCH Modified RedoMap to use a new field in ROM rsrc entries that ; points to rsrc data. ; <1.6> 6/30/89 GGD Added default combo selection when PRAM combo is 0, or out of ; range. ; <1.5> 6/15/89 BBM Added support in InitResources for combinational resource in ; ROM. The ROM resource map is now generated at bootime depending ; on the combination byte stored in Pram. ; <1.4> 6/12/89 dba Changed the logic that checks for old printing glue opening the ; printer file. ; <1.3> 3/3/89 CCH Now checks IntlSpec to see if Smgr has been initialized instead ; of ExpandMem. ; <1.2> 2/17/89 CSL Clean up PartRead and UpdateResFile for 32 bit clean. ; <1.1> 11/10/88 CCH Fixed Header. ; <1.0> 11/9/88 CCH Adding to EASE. ; <1.2> 10/27/88 PKE added script manager support to initresource ; <1.1> 8/26/88 BBM Example to show how to use ease. ; <1.0> 2/11/88 BBM Adding file for the first time into EASEÉ ;______ EASE Modification History for file RmgrAsm2.a ____________________________________ ; <1.3> 8/30/89 dba changed MapReadError to mapReadErr ; <1.2> 6/29/89 BBM Added vectors for StdEntry and StdExit ; <1.1> 11/10/88 CCH Fixed Header. ; <1.0> 11/9/88 CCH Adding to EASE. ; <1.0> 2/11/88 BBM Adding file for the first time into EASEÉ ;______ EASE Modification History for file RmgrAsm3.a ____________________________________ ; <1.2> 8/30/89 dba changed ResErrAttr to resAttrErr ; <1.1> 11/10/88 CCH Fixed Header. ; <1.0> 11/9/88 CCH Adding to EASE. ; <1.0> 2/11/88 BBM Adding file for the first time into EASEÉ ; ; To Do: ; ;_________________________________________________________________________________________ ; ; Set all undefined conditionals and equates to default state ;_________________________________________________________________________________________ ;_________________________________________________________________________________________ ; ; Macintosh Resource Manager ; ; Written by Bruce Horn 22nov82 to 10sep83 ; Modified by Brian B. McGhie 01jan85 to Present ; Modified by Bryan Atsatt 02oct89 to Present ; ; This file contains the source code for the Resource Manager. It includes files ; which contain toolbox, graftype and sysmacs equates and macro definitions. ; ; As with the OS routines, the Resource Manager routines, with one exception, ; smash A0 and D0 only; all other registers are preserved. LoadResource ; preserves ALL registers. ; ; The Mark menu lists most of the routine entry points; names preceded by an apple ; are external entries (A-Traps), those marked with a diamond are internal entries. ; All external entry points are listed in the Exports section (use Mark menu). ; ; This file is built with the following conditionals: ; ; hasComboResource: true (will always be true!) ; ;_________________________________________________________________________________________ eject ;_________________________________________________________________________________________ ; ; Revision History ;_________________________________________________________________________________________ ; ; 16-Dec-82 BLH Added Add/RmveResource. Massive name changing. ; 21-Jan-83 BLH Updated to new LK file system. ; 11-Feb-83 BLH Returned error codes in InitResources, ; OpenResource ; 17-Feb-83 BLH Fixed bug in CheckLoad ; 25-Apr-83 BLH Rom 3.0 overhaul: ; fixed bug in UpdateResFile, optimizing ; the writes and making it a little quicker ; to call updates. ; Changed openResFile to use the resource ; fork, and to handle more reasonably the ; already-open, not-open, and other error ; conditions. ; CloseResFile now releases all resources ; in the map before closing, compacts the ; resources in the map, and writes out the ; possibly modified map and header. ; (@@Note--CloseResFile does not compact ; yet. Due to a bug in GetHandleSize, ; this feature has been disabled. ) ; The resource file starts at ZERO instead ; of 512. ; Added memory full error handling in ; OpenResFile and CheckLoad. ; Added preLoad capability to initResources ; and OpenResource. ; Added procedure WriteResource. ; Added ResAdded resource attribute. ; Added MAttr, map attributes word, in map. ; MapSize and DataSize are now LONGS. ; Resource manager routines now save ; ALL registers except A0 and D0. ; Added SetResPurge to handle the purge ; hook in the Memory Manager. ; Added CurResFile. ; 12-May-83 AJH fixed bug in InitResources -- shouldn't preload when ; you can't read the map ; 24-May-83 BLH Fixed bug in NewMap--crashes if failed due to unlink bug. ; 25-May-83 BLH Changed interface to CmpString in GetNamedResource. ; 31-May-83 BLH Added CreateResFile, fixed AddResource bugs. ; 1-Jun-83 BLH Added DetachResource. ; 6-Jun-83 BLH Fixed bug in GetNamedResource (didn't search all maps) ; 8-Jun-83 BLH Fixed bug in CloseResource (!) ; 10-Jun-83 BLH Moved compacting and mapwrite from CloseResFile to Update. ; Added routine to close maps in . ; CloseResFile closes all maps if you attempt to close ; Sys.rsrc. UpdateResFile now compacts, since GetHandleSize ; finally works. ; 13-Jun-83 BLH Made SetResAttr, SetResInfo NOT set the mapChanged bit. ; you have to explicitly call ChangedResData to make sure ; the change is written out to the map. ; 18-Jul-83 BLH Added MapCompact attribute bit to minimize resource file ; compacting. Added UniqueID to return a unique ID for a given ; type in the current map. Also, shrunk code approximately ; 60 bytes due to suggestions from Donn Denman. ; 8-Aug-83 BLH Removed BeginSubResource, EndSubResource. Added HomeResFile. ; Added ResErrProc in globals. Made UniqueID return an ; ID which is unique in all open maps. Took out SetEOF ; from UpdateResFile, to allow pre-allocation of the ; resource fork. Put in ResrvMem to reserve low locations for ; locked handles. Added file-order preload and update to ; speed up resource I/O. ; 12-Aug-83 BLH Split Resource Manager into four files: RMgr, RMgrAsm1, ; RMgrAsm2, and RMgrAsm3. Utilities in RMgrAsm2. Added ; CheckGrow to handle the DiskFull condition. CheckGrow ; called from ChangedResource, AddResource, and AddReference. ; Also Added ReallocRes, AllocRes, called from (surprise!) ; changedResource and AddResource to allocate space for ; either a new resource or a resource which has changed ; size and needs to be reallocated at the end. ; 16-Aug-83 BLH Bug fixes and space-savers. ; 29-Aug-83 BLH Fixed bug in SetResInfo, RmveResource (protect bit checked ; in RHndl instead of RAttr) and made CheckGrow handle ; memoryFull condition as well as diskFull. ; AddResource/AddReference now return ResErr=DiskFull or ; MemFull in the case that CheckGrow failed. ; 1-Sep-83 BLH InitResources shouldn't clear ResErrProc. ; Fixed NOP (branch to next instr!), folded cmn code in ; name stuff. Fixed dangling ptr problem (!) caused by ; CheckGrow. Took out dangerous LINK stuff in SetFileIO ; and just used a standard stackframe on first link in ; StdEntry. Made GetCurMap and CloseResFile handle the case ; of no maps open (set curMap to FFxx with ST). Fixed bug ; in LoadResource where errors would not get reported through ; the ResErrProc. AddResource sets the Resource bit in the ; masterPtr, RmveResource and DetachResource clear it. ; 2-Sep-83 BLH MAJOR CHANGE: threw away name ID stuff, made hard offsets ; to the names in the name block stored in the resource entry ; where the nameID was previously stored. This change ; fixed a time-bomb bug which would trash the resource file ; after repeated SetResInfo calls. Also, data lengths in ; the resource file are now LONG integers (4 bytes). Fixed ; CountTypes, GetIndType to return true counts and unique types ; for all open maps, to be consistent with CountResources ; and GetIndResource. ; 6-Sep-83 BLH Added MapReadOnly in MAttr to inhibit writing to the resource ; file and diskFull checking. Added SetResFileAttrs, ; GetResFileAttrs to allow toggling of this bit. ; 8-Sep-83 BLH Fixed bug in CheckGrow which could trash the resource map ; if the handle passed to ChangedResource or AddResource ; was purged. ; 9-Sep-83 BLH Fixed bug in CheckLoad--ResrvMem must preserve A0, so typed ; in .Word $A040 to replace _ResrvMem. Fixed bug in RmveName. ; 10-Sep-83 BLH Fixed bug having to do with protected resources; cleaned ; up usage in UpdateResFile, ChangedResource, WriteResource. ;_________________________________________________________________________________________ ; Version 7.0. Last modified 10-Sep-83 by Bruce Horn. Later changes by BBM. ; All changes from this point on are part of the development of the BigROM. ;_________________________________________________________________________________________ ; 22jan85 BBM started to roll in patches to the rom source. ; 29jan85 BBM Cleaned up a lot of internal tables and comments. ; 02feb85 BBM Changed InitResources to support ROM Resources. Since We ; need some of the ROM Resources (e.g. the sony drvr) at boot time ; before we have mounted (or can mount) the disk, we now call ; InitResources twice. The first time it enables just the ROM ; resources, moving both the map and the master pointers down from ; the ROM. The Second time, it sets up the system resource map from ; off of the disk as the root resource map, and moves various ptrs ; so that the system file is the root map and the ROM map is next ; in line down to ram. This enables people to lock down ROM ; resources without causeing a bus fight, Since the map and pointers ; used are not in ROM. Initresources calls BuildMap, which is new. ; 11feb85 BBM Changed CloseFiles and CloseResFile so they couldn't close ROM ; resource map. This needs to be modified later, as there should be ; a way to override ROM resources. ; 12feb85 BBM RsrcZoneInit now won't try to release rom resources. Also ; changed ReleaseResource so it wouldn't release ROM resources. ; 13feb85 BBM changed the format for the ROM resources associated code had ; to be changed. (see InitResources and BuildMap) ; 18feb85 BBM The ROM resources now work right on switch-lanching. As we ; are now using the new system equate files for the build rom ; proceedure, I had to change one equate (from resource to resourc). ; 27feb85 BBM If you call CreateResFile on a locked disk, an incorrect error ; code was being returned. Bug was that after _Create, no check for ; error was done. Fix was to stuff error code into ResErr and rtn. ; 28feb85 BBM CurResFile now returns zero if the current res file is the ; system resource file, else it returns the actual refnum. ; 03mar85 BBM CloseResfile was wasting time calling DisposeResource when it ; should call DisposHandle directly. (see note in routine's header) ; 05mar85 BBM changed BuildMap to create a read-only zone for the ROM Rsrcs. ; 07mar85 BBM Added Preload3, which is executed if ResLoad is false (in Pre- ; Load), in which case there is no need to access the disk. This ; avoids the n-squared search on the curmap for preloadable rsrcs. ; 08mar85 BBM The other problem with Preload was that it was checking ; ResPreLoad at the highest level of the loop. Added two utilities, ; FirstR2 and NextR2, which do the duplicate FirstRes and NextRes ; except they check the preload bit as they scan through the map. ; 09mar85 BBM Fixed CheckLoad. Now it only checks the size once when it is ; loading in a resource, instead of checking the size twice. ; 12mar85 BBM added a ram cache for HandleScan. Involved new low memory ; variables and modifying routines that would invalidate cache. ; Added SaveCache routine. ; 13mar85 BBM fixed a bug in release resource where it was trying to release ; the ROM resources. Fixed a stack problem in FNInit. ; 14mar85 BBM fixed preload to zero all handles of the new map, as the map ; read in may have bogus info in those fields. ; 15mar85 BBM fixed 32k limit on the size of resources. ; 19mar85 BBM SaveCache should only save words for D4-D6. FNInit should pop ; stuff off the stack using ADDQ #4,SP. Preload/2/3 should check to ; see if any rsrcs exist first. StdExit now zeros A0 for Duvall. ; 22mar85 BBM InitResources/Buildmap calculates new handles for ROMresources ; but didn't mask off high byte of the masterpointer (which could be ; locked, etc.). ; 22mar85 LAK&BAS PreLoad3 only created handles for resources that WEREN'T ; preloaded. Also, _NewEmptyHandle caused the map to move and A2 ; was pointing into it, so A2 was changed to be an offset into the ; map around the _NewEmptyHandle call. ; 23mar85 BBM Calling GetMap/GetCurMap with an invalid refnum passed back an ; error but left most regs setup pointing to the system map. The old ; finder blindly used these regs without checking the error CC. So ; to be compatible in the new ROM we make the curmap, topmap. ; 25mar85 BBM the fix on 22-mar-85 only preserved A2. A3 must also live. ; 28mar85 BBM In order to access the ROM Resources nearly all the time, we ; now set the low memory variable SysMap = 1 (the ROM map refnum). ; This has implications to a majority of the RMGR routines. RMGR ; routines that check rsrc ResProtected bit or check MapReadOnly bit ; will not need added code to protect them (eg. SetResInfo) ; 29mar85 BBM Initresources(BuildMap) was hard wired to $1C which currently is ; always in MTypes. Rather than make life hard in the future, redid ; code to add in the value in MTypes and not use $1C. ; 02apr85 BBM fixed HomeResFile to return correct RefNum. ; 03apr85 BBM Finished work of 29-mar-85. DetachResource and ; ReleaseResource now set ResErr (ResChngBit = -198) if ResChanged ; bit is set. AddResource and AddReference would not allow you to ; add to the system map. ; 09apr85 BBM made FirstR2/NextR2 more general. These routines now use D1 ; to determine which bit of RAttr to test on the lowest level. This ; fix enables both UpdateResource and Preload to use FirstR2/NextR2. ; 10apr85 BBM Added a fix that was from Bud Tribble to ORFCommon. This is a ; fix for some print drivers. Fixed GetResInfo so that if a pointer ; is passed which is nill, it doesn't attempt to write out that var. ; Added new routine DoRomEntry to recover handles in the ROMZone, ; also had to save off ROMZone when created and made ReleaseResource ; work in the RomZone ; 11apr85 BBM Change DoRomEntry to support a new interface with the Memory ; manager. Added routine CheckMap, which does some minimal error ; checking on rsrc maps. ; 16apr85 BBM GetResource and GetNamedResource now return an error if they ; couldn't find the resource. _NewHandle in routine NewMap didn't ; set ResErr if it returned an error, now it does. UpdateResFile ; didn't set ResErr if MapReadOnly is set, now it does. GetIndResource ; sets ResErr if input index is zero or negative. ChangedResource ; and SetResInfo now return error condition if ResProtected is set. ; WriteResource now sets ResErr if Map is ReadOnly or Res not changed. ; CloseResFile returns error code if UpdateResFile fails as well. ; 18apr85 BBM now Preload, if ResLoad is false, doesn't call NewEmptyHandle. ; SetResPurge now points to the correct Zone. ; 22apr85 BBM Finished the one map deep calls. Added Seven new entry points: ; Get1Resource, Get1IndResource, Get1NamedResource, Get1IndType, ; Count1Types, Count1Resources, Unique1ID. (added Std1Entry). ; 23apr85 BBM Fixed the checks in GetResInfo which see if the pointers to ; var parameters are nill. Started to remove references from RMGR. ; Also fixed the switcher, to keep all RMGR files open & circumvent ; the RMGR Andy H. did a MOVE.L SysMapHndl,TopMapHndl and called ; RsrcZoneInit. Most likely he is not the only one doing it, so we ; added an error check in closefiles, which corrects TopMapHndl if ; it is pointing below the ROMMapHndl. ; 29apr85 BBM Fixed bug in Preload (it would only load in one rsrc). Fixed ; bug in CheckMap. ; 30apr85 BBM GetIndResource, GetResource and GetNamedResource all save the ; HandleScan cache. Sped up GetIndResource and CountResources by ; not dealing with system references. ; 01may85 BBM Sped up HandleScan by a whole lot!!!!! Added a new exit for ; routines called SubA2Found, to speedup IDScan and TypeScan. Sped ; up DoRomEntry and CountITypes. ; 02may85 BBM Added new trap GetMaxSize. Fixed a bug and (while there) sped ; up GetIndResource. ; 06may85 BBM Preload could save a word by preload calling GetMap. Andy H ; looked at code and suggested some cleanups in SaveCache, SizeRsrc, ; RdRsrc, RdData, GetHS, HomeResFile, CloseResFile, MoveNames, and ; added some stuff for the font manager. ; 07may85 BBM Started speed up on Preload, added SuperLoad & GetMaxSize. ; 08may85 BBM fixed a bug in CheckMap (death occured if there were no named ; resources). ; 09may85 BBM finished the first whack at SuperPreload. ; 10may85 BBM Added new routine GetRsrcCnt which can be used in conjunction ; with a DBRA D4, instead of GetEntries/NextEntries (forSpeed). ; Modified FirstR2, NextR2, Preload accordingly. ; 13may85 BBM Sped up FirstRes/NextRes and combined with FirstR2/NextR2 for ; Space as well as speed. ; 14may85 BBM Fix ORFCommon to use less stack & be a little faster. ; 16may85 BBM made SysMap = RomMap = 2 to fix a bug in Lotus where they were ; trying to do file IO with the bogus ROM map refnum. ; 17may85 BBM patched out superload, since it was superslow. ; 20may85 BBM fixed bug in SpaceAt to setup D1 before call to NextRes. Also ; fixed bug in HandleScan (an off by one bug). Also made the check ; in AddResource less strict, to fix a bug in "Printer Installer". ; Stuffed the MRefNum in the ROM Map with 2, not 1 (see BuildMap). ; 21may85 BBM Backed out change (20may85) to AddResource, in favor of a fix ; in DoRomEntry. Fixed SkipToEntry to handle an offset of 64k. ; 22may85 BBM CloseResFile didn't shut down system right. DetachResource, ; when passed a nill handle went ahead and munged random memory. I ; put the fix into StdResEntry to fix similar problems elsewhere. ; 30may85 BBM made A2/A3 offsets for every IO call. (see WrData2/RDData2). ; 31may85 BBM ReallocRes assumed D1 preserved across SpaceAt. Fixed same. ; 03jun85 BBM Fixed a bug in IO calls by forcing A4 to be even on entry. ; 07jun85 - 13jun85 ; BBM made a new entry Called 'OddSize', which gets four bytes out ; of memory and stuffs it into D0. Finished first massive pass at ; UpdateResFile. Eliminated use of one low memory variable. ; 18jun85 BBM GetIndResource sped up and fixed (wrong value in D4 cache). ; 19jun85 BBM fixed bug related to ResOneDeep stuff (in nextmap). ; 20jun85 - 24jun85 ; BBM rewrote superpreload and various stuff to accomodate different ; loading sequence on preload. (speed improvement). ; 26jun85 BBM made onedeep flag a byte instead of a word. Remaining byte is ; used for RomMapInsert. Note on clearing ResOneDeep we still clear ; the whole word, as RomMapInsert still needs to be cleared. ; 27jun85 BBM finished pulling ROM Resources. ; 29jun85 BBM _MaxBlock/_NewHandle may move memory (resource map) so need to ; keep A2 valid in _UpdateResFile. ; 30jun85 BBM optimised RLocnNew. Fixed CmpFrmDsk. ; 01jul85 BBM fixed UpdateResFile (again?!). ; 02jul85 BBM start code thought that ResErrProc is already setup. Added new ; entries into FirstRes/NextRes which zero D1 on entry. ; 03jul85 BBM cleaned up UpdateResFile. ; 08jul85 BBM Fixed some subtle wierd cases in UpdateResFile routines. ; 09jul85 BBM changed lowmem defs, pulled out new updateresfile for now, made ; powerup code work right with the ROM resource pullout. ; 10jul85 BBM tried a fix in OpenRF in conjunction with the new file system. ; Fixed a bug swapping rom map in and out, which involved curmap. ; Finally fixed UpdateResFile - its about as fast as it can be. ; 11jul85 BBM fixed up superload to work with the new ROM insert stuff. ; 15jul85 BBM backed out enhancement to CurResFile (which returned zero if ; CurMap = SysMap). F/DA Mover was walking through FCB Queue using ; zero as a valid refnum. ; 18jul85 BBM added some more error checking on the handlescan cache. Three ; calls mess with the map after setting up the cache (AddResource, ; RmveResource, and SetResInfo) so fixed them as well. ; 19jul85 BBM Sped up RsrcZoneInit. ; 22jul85 BBM Fixed bugs connected with CloseResFile (assumed SysMap <= 2). ; Removed the MaxSizeRsrc call to make room in ROM. ; 12aug85 BBM Sped up CloseResFile. Cleaned up most of the special code for ; the ROM map, and did house cleaning. ; 13aug85 BBM Compacted some code. ; 14aug85 BBM RMGR should work with the map in the front, so fixed SpaceAt, ; CheckMap and SetRFEOF. ; 20aug85 BBM started a new format for getting address of a rom rsrc. ; 21aug85 BBM fixed and adjusted SizeResource and MaxSizeRsrc, and added new ; trap called RsrcMapEntry. ; 22aug85 BBM made a standard entry and exit for utility routines called ; SaveRegs and RestRegs. Fixed SetResInfo. ; 24aug85 BBM fixed RmveName. ; 26aug85 BBM cleaned up more, Replaced SpaceAt to work with map at front. ; Added OpenRFPerm. Removed a lot of SetEOF Calls. ; 27aug85 BBM made massive changes to InitResources and BuildMap. Added new ; routines. This version of RMGR depends on new format of ROM Rsrc's. ; 28aug85 BBM made RomRsrcStart an offset, not hardwired to $40001A. ; 29aug85 BBM fixed two bugs during InitResoruces. ; 04sep85 BBM added routine SizeFits to help in SuperLoad. ; 05sep85 BBM made OpenRFPerm work right. ; 09sep85 BBM fixed bug in AllocRes/ReallocRes. ; 11sep85 BBM fixed bug in MaxRFEOF (wrong if data before and after map). ; 12sep85 BBM fixed bug in updateresfile. ; 14sep85 BBM AddResource inserts rsrc entry at end of rsrc entries for that type. ; 17sep85 BBM Fixed NewMap to check whether map exists if ResFile is open. ; 19sep85 BBM Fixed NewMap to really check if this is a new format preload file. ; 09oct85 BBM fixed UpdateResFile (file's first rsrc needed compaction). ; 10oct85 BBM didn't fix right on 09oct85, but now UpdateResFile is great! ; (But AllocRes wasn't. forgot to subtract resdataoffset from file loc) ;________________________________________________________________________________________ ; BETA ROMS LAUREL & HARDY (all changes from this point are witnessed by two ; people, the second person in lowercase) ;________________________________________________________________________________________ ; 17oct85 BBM/jtc MacWrite 2.2 uses AddReference and RmveReference. The fix ; will be to keep the traps but strip the parameters off the stack ; and return with ResError set as an error. This makes these two ; traps equivalent to nop routines. ; BBM/jtc UpdateResFile could be passed a bad map and get caught in ; an infinite loop. Now it cann't get caught in an infinite loop. ; 21oct85 BBM/jtc In UpdateResFile mark ResErr with error if we abort. ; 27oct85 BBM Added some vectors for the low level routines. (True Paranoia!) ; Changed NewMap to return error if no map found. ; 30oct85 BBM Changed the way that OpenResFile and OpenRFPerm worked with the ; permission in order to accomidate the segment loader. ;; 04nov85 BBM RmveResource of a ROM resource tried to do SetEOF on ROM RefNum, which is an ; illegal file call. This fix skips the eof call if it is the rom refnum. ; This change is needed if we want ROM Override to work correctly. ; 06nov85 BBM MicroSoft's Word was going behind the font manager's back, which ; caused the font cache to become invalid. So I now invalidate the ; Font Manager's cache if I release a resource of type 'FONT'. ;_________________________________________________________________________________________ ; POST LONELY HEIFER FIXES ;_________________________________________________________________________________________ ; <06jan86> BBM Took out three lines that shouldn't have been in the routine ; CmpFrmDsk. This fixes a bug in UpdateResFile. ; <08jan86> BBM If UpdateResFile cann't get at least 4k for a buffer it dies. ; Fixed UpdateResFile so it can use a 1k buffer off of the stack. ; <09jan86> BBM cleaned up the way it found space on the stack for UpdateRes. ; <13jan86> BBM Fixed GetMaxLoad to get the right data. (PreLock, etc., were not ; addresses, they were offsets.) This fixes superpreload. ; <19feb86> BBM Made some modifications to work under MPW ; <13may86> BBM Fixed a bug in updateresfile. The bug manifested itself when ; compacting from disk and slideing the resource forward in the buffer ; from one to three bytes. This caused the resource size to overwrite ; itself. Thus some resources could be several meg long. ; JTC Changes in all 1,2,3 files for 32-bit support. Trick change ; to DoROMEntry presumes that rel handles in mem mgr block headers ; have only 24 bits, as in the Leung/Fung 32-bit memory manager. ; bbm added support for mpw includes. ; bbm font manager wanted its cache invalidated on opening and ; closing resource files. Helps new font manager be compatible with ; some old applications. ; bbm made the check for a bad map more robust (rmgrasm2(checkmap)). ; bbm one of the macplus patches to updateResFile did not get rolled ; in. UpdateResFile now finds buffer space more intelligently. ; bbm memory manager is now long word aligned, which changes ROZinti. ; bbm fixed dumb mistake in patch that was rolled in (see C268). ; agh 32 Bit address Fixes. Removed dozens of asm bra size warnings. ; UNIX 8 byte master pointer mods to ROZInit. ; bbm added rGetResource trap to rmgrasm3.a. This trap reverses the ; order of the system and rom map when doing a GetResource. (In reality, ; _GetResource is called with romMapInsert false. If that fails ; _GetResource is called with romMapInsert true.) ; bbm fixed rGetResource trap to rmgrasm3.a. (stack cleanup problem) ;_________________________________________________________________________________________ ; ; Files Combined ;_________________________________________________________________________________________ ; ; <02oct89 bpa> Combined ResourceMgr.a, RmgrAsm1.a, RmgrAsm2.a & RmgrAsm3.a into one ; file: ResourceMgr.a. ; <03oct89 bpa> Modified ZFirstRes/ZNextRes/FirstRes/NextRes so can be called with ; D1 = resIgnored (0). Made two copies of Get1IndResource/GetIndResource, ; one if hasResIgnored and the other if not; modified the one for ; hasResIgnored so manages ResIgnored attribute. ; <04oct89 bpa> Modified PreLoad and UpdateResFile so will clear ResIgnored attribute bits ; in all entries in map. Added new routine ClearIgnore. ; <05oct89 bpa> Added new routine ChkTypeIgnored which checks to see if all entries for a ; given type are ignored; modified CountITypes and TypeScan to call it. ; Modified CountResources/Count1Resources so doesn't count ignored ; resources. Modified IDScan so skips any matching ID whose ignore bit is ; set. ; <06oct89 bpa> Added new routine TypeScanAll which does not ignore types; modified ; AddNewRef and RmveResource to call it rather than TypeScan. Modified ; IDScan so skips any entries whose ignore bit is set. Added new routine ; IDScanAll which does not ignore types; modified UniqueID/Unique1ID to call ; it (& TypeScanAll) rather than IDScan. Modified GetResAttrs and ; SetResAttrs to force ResIgnored bit clear. Modified GetNamedResource and ; Get1NamedResource so skips any entries whose ignore bit is set. ; <07nov89 bpa> Added support for undefined conditionals (sets them to default state). ;_________________________________________________________________________________________ LOAD 'StandardEqu.d' include 'HardwarePrivateEqu.a' include 'UniversalEqu.a' ; <1.3> include 'ResourceMgrPriv.a' include 'FontPrivate.a' ; stbstb include 'Decompression.a' ; stb include 'InternalOnlyEqu.a' ; include 'SysPrivateEqu.a' ; stb include 'PrintTrapsEqu.a' ; BT string asis ;_________________________________________________________________________________________ ; ; Export all external entry points ;_________________________________________________________________________________________ RMgr PROC EXPORT EXPORT AddResource ; Add a resource to the resFile. EXPORT AddReference ; a nop routine added back in for MacWrite 2.2 <17oct85> BBM EXPORT ChangedResource ; Called to mark resource to be written EXPORT CloseResFile ; Given refnum, closes the resource EXPORT Count1Resources ; $A81A (26) OneMapDeep version of CountResources EXPORT Count1Types ; $A81C (28) OneMapDeep version of CountTypes EXPORT CountResources ; Given type, return number of resources EXPORT CountTypes ; Returns number of types in current rsrc EXPORT CreateResFile ; Given filename, create a null res file EXPORT CurResFile ; Returns the current resource file refnum EXPORT DetachResource ; Given handle, detaches it from resources. EXPORT Get1IndResource ; $A81B (27) OneMapDeep version of GetIndResource EXPORT Get1IndType ; $A81D (29) OneMapDeep version of GetIndType EXPORT Get1NamedResource ; $A820 (32) OneMapDeep version of GetNamedResource EXPORT Get1Resource ; $A81F (31) OneMapDeep version of GetResource EXPORT GetIndResource ; Given index and type, returns handle EXPORT GetIndType ; Given index, returns type EXPORT GetNamedResource ; Given name and type, return handle EXPORT GetResAttrs ; Given handle, get the attributes of a resource EXPORT GetResFileAttrs ; Given refnum, return resfile attributes. EXPORT GetResInfo ; Given handle, get the info of a resource EXPORT GetResource ; Given an ID and type, give handle back EXPORT HomeResFile ; Returns refnum of an object's home resfile EXPORT InitResources ; One-time call, initializes resource manager ; and opens Sys.resource (!refnum) EXPORT InitRSRCMgr ; initializes the Resource Manager, called from StartInit EXPORT LoadResource ; Given handle, loads resource from source EXPORT MaxSizeRsrc ; $A821 (33) size of rsrc without hitting disk EXPORT OpenResFile ; Given filename, opens and returns refnum EXPORT OpenRFPerm ; Given filename, permissions, and volrefnum, ; ... do OpenResfile EXPORT ReleaseResource ; Given handle, releases resource. EXPORT ResError ; Returns error code, 0 if no error. EXPORT rGetResource ; $A80C (12) getresource/reverse sys & rom map. <14jan87> BBM EXPORT RmveResource ; Remove a resource from the resFile EXPORT RmveReference ; a nop routine added back in for MacWrite 2.2 <17oct85> BBM EXPORT RsrcMapEntry ; given handle, return offset to rsrc entry EXPORT RsrcZoneInit ; Zero all handles in the system map ; ... which point to application heap zone EXPORT SetResAttrs ; Given handle, set the attributes of a resource EXPORT SetResFileAttrs ; Given refnum, set resfile attributes. EXPORT SetResInfo ; Given handle, set the info EXPORT SetResLoad ; Auto-Load on get? EXPORT SetResPurge ; Write resources when purging? EXPORT SizeResource ; Returns 4 byte resource size (may go to disk!!) EXPORT Unique1ID ; $A81E (30) OneMapDeep version of UniqueID EXPORT UniqueID ; Given type, return a unique ID for that type EXPORT UpdateResFile ; Given refnum, update resource file EXPORT UseResFile ; Given refnum, sets current res file. EXPORT WriteResource ; Given handle, writes resource to file EXPORT vSuperLoad ; vector to routine superload <27oct85> BBM EXPORT vCmpFrm ; vector to inside UpdateResFile <27oct85> BBM EXPORT vNewMap ; vector to routine NewMap <27oct85> BBM EXPORT vCheckLoad ; vector to the checkload routine. <27oct85> BBM EXPORT vRMgrStdEntry ; vector to the StdEntry routine. <1.2> BBM EXPORT vRMgrStdExit ; vector to the StdExit routine. <1.2> BBM EXPORT StdZEntry ; <9> rb EXPORT Std1Entry ; <9> rb EXPORT RStdExit ; <9> rb EXPORT RdData ; <9> rb EXPORT WrData ; <9> rb EXPORT SaveRegs ; <9> rb EXPORT SpaceAt ; <9> rb EXPORT CheckGrowAt1 ; <9> rb rb EXPORT RefHandle ; <9> rb EXPORT AddNewRef ; <9> rb EXPORT AddNewRefWithoutUpdate ; kc EXPORT AddName ; <9> rb EXPORT RRentry6 ; <9> rb EXPORT ROMOpenRFPerm ; <9> rb EXPORT HCreateResFile,HOpenResFile ; EXPORT FPCallROvr ; bt EXPORT FPCallCacheFlush ; bt EXPORT FPCallDonnDecompress ; bt EXPORT FPCallGreggyPrepare ; bt EXPORT FPCallGreggyDecomp ; bt EXPORT FPCallGreggyDone ; bt EXPORT FPCallResErrProc ; bt EXPORT FPCallCountIExit ; bt EXPORT FPvCmpFrm ; bt EXPORT SuperLoad ; bt EXPORT NewMap ; bt EXPORT CheckLoad ; bt ;_______________________________________________________________________________ ; Register conventions throughout the Resource Manager: ; ; A0, D0, D1, D2, D7 scratch. ; ; A1 is the handle to the resource ; A2 points to an entry in the map ; A3 points to the beginning of a sub-block ; A4 is the map handle ; ; D3 is the resource type, if any ; D4 is the number of resource entries (-1) for looping ; D5 is the number of types (-1) for looping ; D6 is the resource map reference number ; ; A6 is always LINKed, through StdEntry. There is only 1 local variable, ; an IOStackFrame. A0 also always points to 8(A6) when returning from StdEntry. ;_______________________________________________________________________________ ;_______________________________________________________________________________ ; ; NullRF the null resource file. ; NullStr just points to the word 0. ; RMGRVersion the resource manager version number ;_______________________________________________________________________________ BLANKS ON STRING ASIS MACHINE MC68020 NullRMSize EQU 30 ; number of bytes in a null map NullStr ; Null String (pascal string 1st byte 0) NullRF ; Null Resource map DC.W 0, DataFirstRes ; ResDataOffset DC.W 0, DataFirstRes ; ResMapOffset (no data!) DC.W 0, 0 ; DataSize DC.W 0, NullRMSize ; MapSize DC.W 0, 0 ; MNext <1.1> DC.W 0 ; MRefNum DC.W 0 ; MAttr DC.W MTyps-NullRF ; MTypes DC.W MNams-NullRF ; MNames MTyps DC.W -1 ; no types listed MNams DC.W 0 ; null string RMGRVersion DC.W 1 ; Resource Manager version number ;_______________________________________________________________________________ ; ; Routine: InitRSRCMgr ; ; Arguments: none ; ; Called By: system initialization sequence in StartInit ; Calls: InitResources ; Destroys: D0-D2/A0-A1 ; ; Function: Call the Resource Manager to load ROM rsrcs and set up his ; indefatigable world. ;_______________________________________________________________________________ InitRSRCMgr ST SysMap ; flag that resources are not inited CLR.L TopMapHndl ; tell the res mgr that it's start time move.l ExpandMem,a0 ; init override flags kc clr.b ExpandMemRec.emScanOverrideMaps(a0) ; turn off ScanOverrideMaps kc clr.w ExpandMemRec.emLastMapOverridden(a0) ; flush override cache. kc clr.w ExpandMemRec.emOverrideMapRefNum(a0) ; flush override cache. kc ; kc CLR.W -(SP) ; Save room for function result _InitResources ; Init ROM resource file ADDQ #2, SP ; Assume success RTS ;_______________________________________________________________________________ ; ; Routine: FUNCTION InitResources: INTEGER; ; ; Arguments: 8(A6) (output.W) Refnum of Sys.rsrc map ; ; Called By: A-trap through Dispatcher ; Calls: StdEntry, NewMap, PreLoad, StdZeroExit, BuildMap ; ; Function: Now a Two-time call, in order to support ROM Resources. First, ; it sets up the ROM resources as the Current and System (& only) ; Map in memory. Second call initializes resource manager & opens ; Sys.rsrc switching pointers to make it the System map and the ; Rom map and the current map. ; Returns the reference number of the Sys.rsrc map. ; Sets ResLoad to TRUE initially, in PreLoad. ;_______________________________________________________________________________ IMPORT SmgrInitialize ; InitResources ; deleted the stuff here that called FixSMgrWorld: was never executed <07/02/89 pke> CLR.L HSCHandle ; Invalidate cache <12mar85> BBM BSR StdZEntry ; Save regs <11jul85> BBM TST.L TopMapHndl ; are the ROM resources "loaded in"? <31jan85> BBM BGT.S @skipROM ; CC=LE means to build rom map from scratch <27aug85> BBM CLR.L ResErrProc ; clear for start code <27aug85> BBM BSR ROZInit ; initialize a Read-Only-Zone MOVE.L A0,TopMapHndl ; Save handle as top map MOVE.L A0,SysMapHndl ; and as system map MOVE.L OneOne,SysMap ; Make SysMap & Curmap refnum = 1 BSR ReDoMap ; set up map from rom image (Returns A1 Ptr) CLR.L MNext(A1) ; Zero next map handle BRA.S @exit ; and exit through StdExit @skipROM LEA theZone, A3 ; ... else do full load,Point to theZone. MOVE.L (A3), -(SP) ; Save the current zone MOVE.L SysZone, (A3) ; Set system heap for system resource map. LEA SysResName, A1 ; Point to name of system resource. MOVEQ #$00,D0 ; nil dir id BSR NewMap ; Load in map, refnum in D6, result in D0. MOVE.L (SP)+, (A3) ; Restore the zone MOVE.W D6, 8(A6) ; Return result/error code. TST.L D0 ; Test newMap result in D0. BLE.S @exit ; if <=0, error or already open. MOVE.L A4,TopMapHndl ; Save handle as top map <05sep85> BBM MOVE.L A4,SysMapHndl ; Save handle as sys map <05sep85> BBM MOVE.W D6,CurMap ; set up curmap <09jul85> BBM MOVE.W D6,SysMap ; set up sysmap <10jul85> BBM BSR PreLoad ; Preload required resources... <31jan85> BBM BSR ReDoMap ; restore the ROM map (Returns A1 pointer) MOVE.L SysMapHndl,MNext(A1) ; next map in link from rom is system MOVE.L SysMapHndl,A1 ; get handle to system map MOVE.L (A1),A1 ; and dereference system handle CLR.L MNext(A1) ; sysmap is last link in chain BSR.S RomOverRide ; check which rom rsrc's to override move.l IntlSpec,D0 ; if IntlSpec is not set up, <1.2><1.3> addq #1,D0 ; go set it up. <1.2><1.3> BigJsr SmgrInitialize,a0 ; @exit ; Rolled in InstallProc rolled in to set emScanOverrideMaps to true here. move.l ExpandMem,d0 beq.s @noExpandMem move.l d0,a0 move.w #-1,ExpandMemRec.emScanOverrideMaps(a0) @noExpandMem BRA StdZeroExit ; ...and exit. ;_______________________________________________________________________________ ; ; Routine: RomOverRide 65446 (utility) ; ; Arguments: None ; ; Called By: InitResources ; Calls: _GetResource ; ; Function: Checks to see if there is a override resource in the new file ; opened. If there is, it executes that resource. ; ; NOTE: The override resource must be preloaded, locked, & nonpurgable. ;_______________________________________________________________________________ ROVR EQU $524F7672 ; ROVR = 'ROvr' (type of override rsrc) RomOverRide ; new routine <27aug85> BBM SUBQ #4,SP ; Save room on stack for handle PEA ROVR ; rsrc type for override MOVE.W #0,-(SP) ; rsrc ID of 0 MOVE #-1,RomMapInsert _GetResource ; get the override rsrc SUBQ #4,SP ; Save room on stack for handle PEA ROVR ; rsrc type for override MOVE.W #0,-(SP) ; rsrc ID of 0 _GetResource ; get the override rsrc MOVEQ.L #0,D1 MOVE.L (SP)+,D0 ; Check to see if it exists BEQ.S @Lx MOVE.L D0,A0 ; get ready to execute this resource MOVE.L (A0),A0 ; dereference handle Move $8(A0), D1 @Lx MoveA.L (SP)+, A1 Move.L A1, D2 BEQ.S @L0 MoveA.L (A1), A0 Move $8(A0), D2 @L0 Cmp D2, D1 BHI.S @L2 Tst.L D0 BEQ.S @L1 Cmp.L A1, D0 BEQ.S @L1 Move.L A1, -(SP) Move.L D0, -(SP) _ReleaseResource MoveA.L (SP)+, A1 @L1 Move.L A1, D0 BEQ.S ROvrOut @L2 MoveA.L D0, A0 MoveA.L (A0), A0 FPCallROvr ; FlashPort hint attachment point JSR (A0) ; and execute handle ROvrOut RTS ; and return ; <1.5> Equates ComBFSz EQU 5 ; combo bitfield size MemHeadSz EQU 8 ; size of memory header MaxComInd EQU 4 ; maximum valid combo field index RNmOff EQU $F ; offset from past the combo field to the name size <3> ;_______________________________________________________________________________ ; ; Routine: ROZInit (utility) ; ; Arguments: A0 (output.L) Handle to the Map in the ROZ ; A2 (output.L) Pointer to the Map up in the ROM ; RomMapHndl (output.L) Handle to the Map in the ROZ ; ; unchanged: A3-A7,D1-D7 ; trashes: A1-A2,D0 ; ; Called By: InitResources ; Calls: _BlockMove, _InitZone, _NewHandle, _NewPtr ; ; Function: Builds a new zone in the system heap. This zone is a Read Only ; Zone. The size of the new zone can be calculated by the fomula: ; ; bbm memory manager is now long word aligned, which changes ROZinit. ; agh Make master pointer size 8 bytes for use with UNIX 32 bit ; memory mgr. ; ;_______________________________________________________________________________ ; ; Size = zoneheader + zonefooter + longwordalignbias + slop ; + (12 + block of 4 master pointers) ; + (12 + size of master pointer block) + (12 + size of map) ; Size = 52 + 12 + 12 + (12 + 32) + (12 + sizempb) + (12 + sizemap) + slop ; Size = 144 + sizebmp + sizemap + slop ; Size = $90 + 8*X + Y+slop ; (where X = number of rsrc's ; Size = 8*(#$18 + X) + Y ; and Y = size the map) ; ;The old stucture of the ROM is as follows: ; ROMRsrcStart: (long) ; offset to Rom Rsrc stuff ; Rom Rsrc Stuff ; X: (2) number of rsrc's in rom ; Y: (2) size of rom rsrc map in rom ; Map: (Y) the rom map ; rsrc's: (x) the rsrc's ; ;The new stucture of the ROM is as follows: ; RomBase ; 1A (4) offset to Rom Resource Structure Table ; ; Rom Resource Structure Table ; 0 (4) offset to first Resource Entry ; 4 (1) maximum valid index in parameter ram [v] ; 5 (1) Size of Combo Bit Field (v) ; 6 (2) Version ; 8 (2) Size of memory block header ; ; Hiram Resource Entry (all are offsets from base of rom) ; 0 (v) combo bits ; v (4) link to next Resource ; v+4 (4) offset to data for this rsrc ; v+8 (4) Resource Type ; v+C (2) Resource ID ; v+E (1) Resource Attributes ; v+F (1) length of Resource name [n] ; v+$10 (n) Resource name ; v+$10+n (0-3) align 4 ; g(v+$10+n) (8/12) memory block header ; g(v+$10+n)+8 (y) Resource Data [or g(v+C+n) + 12, depending on which mem mgr] ; x+y (0-3) align 4 ; ; where g(w) = w + ((4 - (w mod 4)) mod 4) ; ;_______________________________________________________________________________ ROZInit ; new routine <27aug85> BBM <1.5> bsr CountCombos ; to determine the sizes <1.5> move.l d0,d5 ; save count in D5 move.l d1,d6 ; save map size in d6 moveq #$18,d0 ; clear high word (D0 will be size of ROZ) <1.5> add.w d5,d0 ; add in number of MP's asl.l #3,d0 ; multiply by 8 (the size of a MP) add.w d6,d0 ; Add in size of map [D0 = 8*(#$10 + X) + Y] ; Note to accomodate Figment, we make the ROZ larger. -JC add.l #1000,d0 move.l d0,a1 ; Save off Zone size for later _NewPtr ,SYS ; no error checking. If failure, system dead. MOVE.L theZone,-(SP) ; save current zone till after map build CLR.L -(SP) ; pGrowZone = 0 MOVE.W #4,-(SP) ; cMoreMasters = 4 ADDA.L A0,A1 ; limitPtr = startPtr + Size MOVE.L A1,-(SP) ; ... and storing to parameter block MOVE.L A0,-(SP) ; setting up parameter block for _InitZone MOVE.L A0,A1 ; save pointer to zone for later MOVE.L SP,A0 ; Point A0 to the paramter _InitZone ; finally get to set up zone BSET #ROZ,flags(A1) ; make this zone a read-only zone MOVE.L A1,theZone ; we want ROM Rsrcs in this new zone ADD.W #$E,SP ; pop off parameter block from stack move.l d5,D0 ; get number of MP's <1.5> ASL.L #3,D0 ; Get the size (size = 8*X) _NewPtr ; get MPB in ROZ. (If failure, system dead.) MOVE.W d6,D0 ; get the size of the map <1.5> _NewHandle ; get map in ROZ. (If failure, system dead.) _HLock ; itÕs always there, so lock it MOVE.L A0,RomMapHndl ; Save this handle. MOVE.L (Sp)+,theZone ; restore current zone RTS ;_______________________________________________________________________________ ; ; Routine: ReDoMap (utility) ; ; Arguments: A1 (output.L) pointer to the map in the ROZ ; ; unchanged: A5-A7,D6-D7 ; trashes: A0,A2-A4,D0-D5 ; ; Called By: InitResources ; Calls: _SetHandleSize, _BlockMove, GetRsrcCnt, SetPL ; ; Function: This routine builds Rom map in the ROZ. ReDoMap assumes that ; the ROZ is already built, and ignores all previous data in ROZ. ;_______________________________________________________________________________ ReDoMap ; new routine bsr CountCombos ; to determine the sizes move.l d1,d0 ; get approximate size of map into d0 move.l RomMapHndl,A0 ; Get the handle to the ROM Map in ROZ move.l A0,A4 ; Save for later _SetHandleSize ; Old resource map could have overrides moveq #$20,d0 ; size of null map lea NullRF,a0 ; get null map from rom move.l (A4),A1 ; Dereference handle to destination _BlockMoveData ; move map down move.w #1,MRefNum(a1) ; and stuff the rom map refnum (so getcurmap works) clr.w -(sp) ; get a buffer on the stack to read in index move.l sp,a0 ; point to stack move.l #$000100AE,d0 ; get selected resource combo index _ReadXPram ; move.b (a0),d3 ; save index in d1 addq #2,sp ; dispose of buffer ; add all the resources, set up the regs to look like: ; a2.l pointer to resource header ; d2.l combo field size ; d3.b index ; d4.w size of memory block header (in bytes) move.l RomBase,a2 ; get pointer to romstart adda.l RomRsrcStart(a2),a2 ; add in offset to Rom Rsrc Stuff moveq #0,d2 ; zero combo bitfield size move.b ComBFSz(a2),d2 ; get combo bitfield size move.w MemHeadSz(a2),d4 ; get size of memory header tst.b d3 ; combo zero means use default (PRAM init'ed) <1.6> beq.s @default ; if invalid PRAM, use machine specific default <1.6> cmp.b MaxComInd(a2),d3 ; check if d3 too big bls.s @good ; @default ; if out of range, or invalid, use default <1.6> movea.l UnivInfoPtr,a0 ; point to the universal ProductInfo record <1.6> move.b ProductInfo.DefaultRSRCs(a0),d3 ; get the default combo <1.6> @good ; ; Test for an optional FPU. Combos 3 and 4 are identical except 3 inludes FPU <2> ; Combos are defined in Rom.r. **** If combos change, make sure test is valid !!!*** <2> cmpi.b #4,d3 ; combo with optional FPU? <2> bne.s nochange ; branch if not combo with optional FPU <2> btst.b #hwCbFPU-8,HWCfgFlags ; FPU installed on board? <2> beq.s nochange ; branch if no FPU installed <2> moveq #3,d3 ; change to combo with FPU <2> nochange ; <2> move.l (a2),a2 ; offset to the first resource. add.l RomBase,a2 ; make offset a pointer @loop ;first check if this combo is valid move.l a2,a0 ; get combo field pointer moveq #0,d0 ; clear upper bytes move.b d3,d0 ; get index lsr.b #3,d0 ; div by 8 add.w d0,a0 ; bump a0 to the right byte move.b d3,d0 ; get index into this byte (index is 0-7) eori.b #$FF,d0 ; reverse index andi.b #7,d0 ; make index correct (index is now 7-0) btst.b d0,(a0) ; check if this resource should be included add d2,a2 ; point at link to next entry (no ccÕs set) beq.s @bypass ; this resource not in current combo, so skip ;add this resource move.l 4(a2),a3 ; get ptr to resource data adda.l RomBase,a3 ; make offset a pointer (cc's not changed) ; set up master pointer move.l RomMapHndl,A0 ; get a pointer to the start of ROZ Zone _HandleZone ; move.l -4(A3),D0 ; Rel handle may have useful hi byte _StripAddress ; Restrict to 24MB range off header adda.l D0,A0 ; Add in offset to MP [-4(A1) is the RelHandle] move.l A3,(A0) ; stuff MP with pointer to rsrc in ROM move.l a0,-(sp) ; push the handle move.l $8(a2),-(sp) ; push the Resource Type move.w $C(a2),-(sp) ; push the Resource ID pea $F(a2) ; push pointer to Resource name IF 0 THEN move.l RomMapHndl,A0 ; get a handle to the map move.l (a0),a0 ; point to the map moveq #0,d7 ; zero high byte move.w $1c(a0),d7 ; save number of types across call ENDIF bsr.s addRomRsrc ; add the resource IF 0 THEN move.l RomMapHndl,A0 ; get a handle to the map move.l (a0),a0 ; point to the map sub.w $1c(a0),d7 ; subtract new number of types lsl.w #3,d7 ; mult by 8 for new map size delta (new type entry) add.w #12,d7 ; for new resource entry add.l d7,MapSize(a0) ; fix map size move.l -8(A3),D0 ; get the size in d0 _StripAddress ; since in 24 bit world size may have flags in upper byte addq #4,d0 ; for size in data add.l d0,ResMapOffset(a0) ; adjust map offset (although all this is bogus) add.l d0,DataSize(a0) ; adjust data size (really bogus, but looks nice) ENDIF @bypass ; move.l (a2),a2 ; offset to next resource header move.l a2,d0 ; check if no more in the list adda.l RomBase,a2 ; make offset a pointer (cc's not changed) bne.s @loop ; go find next link move.w #1,MRefNum(A1) ; save the refnum of the rom file in map rts ; and return ;_______________________________________________________________________________ ; ; Routine: CountCombos (utility) ; ; Arguments: D0 (output.W) number of resources in the rom. ; D1 (output.L) Approximate Size of Rom Resource Map ; ; unchanged: A0-A7,D2-D7 ; Trashed: d0-d1 (upper word trashed, lower word is output) ; ; Called By: ReDoMap, ROZInit ; Calls: not a soul. ; ; Function: Go Through the linked list and count the number in the list and ; get the total size of all the names. ;_______________________________________________________________________________ CountCombos ; new routine <1.5> movem.l d2-d4/a2,-(sp) ; save d0-d1/a0 across call move.l RomBase,a2 ; get pointer to romstart adda.l RomRsrcStart(a2),a2 ; add in offset to Rom Rsrc Stuff moveq #0,d2 ; zero combo bitfield size move.b ComBFSz(a2),d2 ; save combo bitfield size move.l (a2),a2 ; offset to the first resource. add.l RomBase,a2 ; make offset a pointer moveq #0,d0 ; clear count moveq #0,d1 ; clear total name size moveq #0,d3 ; clear temp name size @loop addq #1,d0 ; add one to the count of the resources add d2,a2 ; jump past the combo bit field move.b RNmOff(a2),d3 ; get the name size (only get one byte!) bmi.s @resourceNotNamed ; donÕt add the name size if not named <13> stb add.l d3,d1 ; add into total name size <3> <13> stb @resourceNotNamed ; <13> stb move.l (a2),a2 ; offset to next resource header move.l a2,d4 ; check if no more in the list add.l RomBase,a2 ; make offset a pointer bne.s @loop ; go find next link ; to get approx size of map ; use headersize + 8*n + 12*n + namesize ; 28 + (20)*n + d1 ; where n is number of resources and d1 has the size of names. move.l d0,d2 ; get number of resources mulu #$14,d2 ; multiply by size of type entry and resource entry addi.l #$1c,d2 ; add in map header add.l d2,d1 ; add into the size of names movem.l (sp)+,d2-d4/a2 ; restore registers rts ; and return ;_______________________________________________________________________________ ; ; Routine: PROCEDURE AddRomRsrc(theResource:Handle; theType:LONGINT; ; theID:INTEGER; name:Str255); ; ; Arguments: 18(A6) (input.L) handle to the resource ; 14(A6) (input.W) theType ; 12(A6) (input.W) theID ; 8(A6) (input.L) pointer to pascal string ; ; Called By: ReDoMap ; Calls: StdEntry, GetCurMap, AddNewRef, AddName, StdExit ; ; Function: Add a reference to the given resource in the rom map. ;_______________________________________________________________________________ RomAttrs EQU $58 ; the default rom resource attributes ; (protected, locked, sysheap) AddRomRsrc move.w #MapTrue,RomMapInsert ; don't insert ROM Map bsr StdEntry ; Link A6, save regs move.l 18(a6),a1 ; Get handle in A1 (has to be valid!) bsr GetCurMap ; Get the current map for diskFull check move.l 14(a6),d3 ; Put type of resource to add in D3 bsr AddNewRef ; Set up a new reference to the resource ; Returns A2-->reference location. move.w 12(a6),RID(a2) ; Set ID of reference move.w #-1,RNameOff(a2) ; Assume no name yet move.l 8(A6), A0 ; Get pointer to reference name bsr AddName ; Name set in RNameOff(A2). ; A2, A3 preserved and are correct. move.l 18(a6),a0 ; get the handle to the resource move.l A0,RHndl(a2) ; set handle. move.l (a0),a0 ; point at the resource sub.l rombase,a0 ; make a0 an offset into rom move.l a0,RLocn(a2) ; store offset into map move.b #RomAttrs,RAttr(a2) ; set rom resource attributes @9 moveq #14, D0 ; Pop off 14 bytes of parameter bra StdExit ; Restore regs, unlink A6 ;_______________________________________________________________________________ ; ; Routine: PreLoad (Utility) ; ; Arguments: There are no input arguments. ; The world is left in a weird state on exit (no regs dependable). ; ; Called by: (Preload): InitResources ; (Preload2): OpenResFile ; Calls: GetMap, FirstRes, CheckLoad, NextRes ; ; Function: Clear the handle locations for all local (i.e. non-resSysRef) ; resource entries, and load in all resources in the current map ; which have the resPreload bit set. ; ; PreLoad walks through the map in file order. This was done to ; optimize the file I/O and buffer hits. ;_______________________________________________________________________________ Preload ST ResLoad ; Set ResLoad to True (byte operation) Preload2 ; alternate entry for OpenResFile BSR GetMap ; Get the current map <06may85> BBM BMI.S @9 ; if can't find map then exit BSR GetRsrcCnt ; get the first resource entry <10may85> BBM BMI.S @9 ; if no entries just exit @1 ADDQ #RHndl,A2 ; point at the resource entry handle CLR.L (A2)+ ; clear it and point and next rsrc entry DBRA D4,@1 ; if more, loop back, else fall through TST.B ResLoad ; if (ResLoad = False) just return <22apr85> BBM BEQ.S @9 ; ... sure enough resload is false (CC=EQ) BSR.S SuperLoad ; if we can do fast load then this does it <24jun85> BBM BEQ.S @9 ; CC=EQ means that we have loaded in rsrcs @2 MOVEQ #ResPreLoad,D1 ; Which bit to test on the lowest level <09apr85> BBM BSR FirstRes ; Point A2 to 1st preload file-order entry <08mar85> BBM BMI.S @9 ; if none, exit. @3 BSR CheckLoad ; load in the resource. MOVEQ #ResPreLoad,D1 ; Which bit to test on the lowest level <29apr85> BBM BSR NextRes ; Skip to next preload entry in file order. <08mar85> BBM BEQ.S @3 ; If there are more, loop back @9 RTS ; ...and return. ;_______________________________________________________________________________ ; ; Routine: SuperLoad (internal) <06may85> BBM ; ; Arguments: A4 (i/o.L) Handle to the new map ; ; Unchanged: A4-A7,D6 ; Trashed: A0-A3,D0-D5,D7 ; ; Called By: Preload/Preload2 ; Calls: _BlockMove, _DisposHandle, GetEntries, GetMaxLoad, _NewEmptyHandle, ; _NewHandle, _NewPtr, NextEntry, NotFound, SetPL, SetupInBuff ; ; Function: Try to load all of the resources you can in a more intelligent ; fashion. If you cann't then exit with CC=MI. This means you'll ; have to do the old stupid preload. GetMaxLoad determines if ; this is a new format, how much of the file to read in, and reads ; the data into a buffer. ; ; future note - Try taking advantage of all the information in the cache. ;_______________________________________________________________________________ SuperLoad MOVE.L jSuperLoad,A0 ; get the vector from the OSJumptable <27oct85> BBM JMP (A0) ; and go to the routine <27oct85> BBM vSuperLoad ; Def to build dispatch entry <27oct85> BBM BSR GetMaxLoad ; load in as much as we can for super load <24jun85> BBM BMI NotFound ; if nothing to SuperLoad return (old format) BSR GetEntries ; get the first resource entry <07may85> BBM MOVE.L (A4),A1 ; dereference map handle @1 MOVE.L RLocn(A2),D0 ; check if this rsrc is in the buffer <24jun85> BBM AND.L Lo3Bytes,D0 ; mask off attributes CMP.L HSCache,D0 ; offset to end of buffer BGE @7 ; skip to the next one CSS MOVE.L theZone,-(SP) ; save theZone for later <08may85> BBM BTST #ResSysHeap,RAttr(A2) ; which zone do we put this rsrc? BEQ.S @2 ; skip if default zone. MOVE.L SysZone,theZone ; else force system heap @2 MOVE.L RLocn(A2),D2 ; Get offset into file AND.L Lo3Bytes,D2 ; clear high bits. BSR SetupInBuff ; setup D0=size; A0=Ptr2Rsrc CSS BTST #ResLocked,RAttr(A2) ; if locked do NewPtr ... SUBA.L (A4),A2 ; (Make A2 an Offset) SUBA.L (A4),A3 ; (Make A3 an Offset) BEQ.S @3 ; ... else do NewHandle <15may85> BBM ; We have a locked resource. Do contortions to ; get the resource loaded low (NewPtr style). MOVE.L D0, D1 ; Save Resource Size. _NewEmptyHandle ; NewEmptyHandle / DisposeHandle pair insures BMI @9 ; that a master pointer will be available CSS _DisposHandle ; without allocating a new master pointer blk BMI @9 ; when we do the for-real _NewHandle. CSS MOVE.L D1, D0 ; Grab block size. _NewPtr ; NewPtr allocates block of desired size low BMI @9 ; and leave roving allocate ptr set to it. CSS _DisposPtr ; DisposPtr leaves the perfect free block BMI.S @9 ; for subsequent NewHandle to allocate. MOVE.L D1, D0 ; Restore block size into D0 @3 _NewHandle ; Get a handle for this rsrc (D0 already setup) BMI.S @9 ; any error go do regular preload stuff MOVE.L A0,D1 ; save off Handle to stuff into map MOVE.L (A0),A1 ; Get Destination into A1 for BlockMove @6 BSR.S SetupInBuff ; note destination already has A1 _BlockMove ADDA.L (A4),A2 ; Make A2 a pointer again ADDA.L (A4),A3 ; Make A3 a pointer again MOVE.L D1,RHndl(A2) ; and tell RMGR resource is loaded in. MOVE.L D1,A0 ; get handle into A0 to setup purge/lock bits MOVE.B RAttr(A2),D1 ; get attrs into D1 to setup purge/lock bits BSR SetPL ; setup purge/lock bits MOVE.L (SP)+,theZone ; restore theZone @7 BSR NextEntry ; go get the next entry to clear handle BPL.S @1 ; if more entries, loop back MOVE.L D7,A0 ; get handle to InBuff into A0 _DisposHandle ; free up the memory @8 MOVEQ #0,D0 ; set completion flag (CC=EQ) RTS ; ... and return no error @9 MOVE.L (SP)+,theZone ; restore theZone @5 MOVE.L D7,A0 ; get handle to InBuff into A0 _DisposHandle ; free up the memory BRA NotFound ; return with error. SetupInBuff MOVE.L D7,A0 ; get handle to Input Buffer (buff may have moved) MOVE.L (A0),A0 ; dereference it ADDA.L D2,A0 ; add in offset (D2 can be odd, Byte stuff follows) OddSize ; added new entry for UpdateResFile <07jun85> BBM MOVE.B (A0)+,D0 ; X.X.X.0 - We want '0.1.2.3' byte order <09may85> BBM LSL.W #8,D0 ; X.X.0.X MOVE.B (A0)+,D0 ; X.X.0.1 SWAP D0 ; 0.1.X.X MOVE.B (A0)+,D0 ; 0.1.X.2 LSL.W #8,D0 ; 0.1.2.X MOVE.B (A0)+,D0 ; 0.1.2.3 - Size=D0, rsrc=A0 RTS ; ;_______________________________________________________________________________ ; ; Routine: GetMaxLoad (internal) ; ; Arguments: D0 (output.L) -1 on error; size of data on good rts ; D7 (output.L) Handle to input buffer ; ; Unchanged: A1-A7,D3-D6 ; Trashed: A0,D0-D2 ; ; Called By: SuperLoad ; Calls: _DisposHandle, _MaxBlock, _NewHandle, NotFound, RdData ; ; Function: Four step process. First, find out how much space is available ; in the application zone without moving anything, or purging ; anything. Second, find out size of resources to be read in. ; Third, get a NewHandle of twice the size to get us some room to ; work in, and toss it away. (This forces the heap to grow as much ; as we will need.) Fourth, get a NewHandle of the size we need ; and read in data. Return with CC=MI or D7=handle of input buff. ;_______________________________________________________________________________ GetMaxLoad ; READ IN MAX AMOUNT TO DISECT IN SUPERLOAD <24jun85> BBM TST.L HSCache ; is there a valid key? BEQ @9 ; wrong format for superload CSS MOVEQ #0,D7 ; D7 is the amount we can grow heap. MOVE.L SP,D0 ; Get top of Stack. _StripAddress ; Want clean arithmetic. SUB.L MinStack,D0 ; Allow some stack margin. CMP.L ApplLimit,D0 ; if ApplLimit is greater then use ... BCS.S @1 ; ... use ApplLimit instead. MOVE.L ApplLimit,D0 ; D0 now has the maximum limit @1 SUB.L HeapEnd,D0 ; if D0 <= HeapEnd BLE.S @2 ; ... then can't grow heap CMP.L #MinFree,D0 ; can the zone grow by the minimum size BLS.S @2 ; ... if not, can't grow heap. MOVE.L D0,D7 ; Stuff D7 with the amount to grow heap. @2 _MaxBlock ; D0 has max space after a compact. CMP.L D7,D0 ; does compact or growheap get us more? BLE.S @3 ; D7 already has max value, MOVE.L D0,D7 ; ... else D7 = amount we can grow heap. @3 MOVE.L HSCache+PreExtra,D0 ; calc how much to read in for superload? <13jan86> BBM BSR.S SizeFits ; check to see if this size fits in buff <04sep85> BBM BPL.S @4 ; CC=PL if this fits MOVE.L HSCache+PreUnlock,D0 ; check if PreUnlock fits <13jan86> BBM BSR.S SizeFits ; check to see if this size fits in buff BPL.S @4 ; CC=PL if this fits MOVE.L HSCache+PreLock,D0 ; check if Prelock fits <13jan86> BBM BSR.S SizeFits ; check to see if this size fits in buff <04sep85> BBM BMI.S @9 ; not even this fits, so exit with error @4 _NewHandle ; by allocating some room <15may85> BBM BMI.S @9 ; if cann't even do this exit _DisposHandle ; else dispose of space to get us some room <15may85> BBM MOVE.L D1,D0 ; need to know size for newhandle <07may85> BBM _NewHandle ; get some space to read in the Rsrcs BMI.S @9 ; and return to preload with error MOVE.L D1,D0 ; get size into D0 for read MOVE.L A0,D7 ; Save off handle of PreLoad input Buffer MOVE.L (A0),D1 ; set up pointer to this buffer MOVE.L (A4),A0 ; Dereference map handle to get offset MOVE.L ResDataOffset(A0),D2 ; get start position in file BSR RdData ; massive read of data into Buff (D6 good) BEQ.S @8 ; if read good return MOVE.L D7,A0 ; get handle to buffer into A0 _DisposHandle ; else dispose of space to get us some room <11jul85> BBM @9 MOVEQ #-1,D0 ; ELSE ERROR RETURN @8 RTS ; SizeFits ; new routine <04sep85> BBM MOVE.L D0,HSCache ; save off for SuperLoad BEQ NotFound ; if nothing to load, set CC's to MI BMI.S @9 ; If CC=MI, just return MOVE.L D0,D1 ; Save off for later ADD.L D0,D0 ; double D0 MOVE.L (A4),A0 ; Dereference map handle ADD.L MapSize(A0),D0 ; add in size of map CMP.L D0,D7 ; Set CC's and return @9 RTS ; ;_______________________________________________________________________________ ; ; Routine: NewMap (Utility) ; ; Arguments: A1 (input.L) pointer to filename ; A1 (output.L) pointer to map ; A2 (output.L) handle to map ; D0 (output.L) result code ; D6 (output.L) file reference number ; ; Called by: InitResources, OpenResFile ; Calls: _Close, _DisposHandle, _GetEOF, _NewHandle, ORFCommon, RdData, ; SetFileIO, _SetHandlesize ; ; Function: Create a new resource map in the RMGR map chain for the given ; resource file. Sets up regs A1/A2/D0/D6 with values for input ; filename. Three possible returns: ; D0 = 0; D6 = MRefNum Map already exists ; D0 = 1; D6 = refnum New map created ; D0 = D6 = -1 Error return ;_______________________________________________________________________________ NewMap MOVE.L jNewMap,A0 ; get the vector from the OSJumptable <27oct85> BBM JMP (A0) ; and go to the routine <27oct85> BBM vNewMap ; Def to build dispatch entry <27oct85> BBM CLR.L HSCache ; invalidate cache always <20jun85> BBM CLR.L HSCHandle ; invalidate cache MOVEQ #HdrSize+PreSize,D0 ; Set length = header size <11jul85> BBM _NewHandle MOVE.W D0, ResErr ; return the error code in ResErr <16apr85> BBM BMI NMNoHandle ; If failed this little newHandle, exit, MOVE.L A0,A4 ; else save handle in A4 <05sep85> BBM BSR SetFileIODirID ; Set up the file IO frame A0 --> BSR ORFCommon ; Open the resource file with name in A1 BEQ.S @1 ; If open was successful, go on CMP.W #OpWrErr, D0 ; Already open? BNE NMNoFile ; If not open, can't handle, else MOVEM.L A2-A4/D6,-(SP) ; save regs across call <17sep85> BBM BSR GetMap ; check to see if map exists <17sep85> BBM MOVEM.L (SP)+,A2-A4/D6 ; restore regs <17sep85> BBM BNE NMNoFile ; If no map then exit with error <27oct85> BBM CLR.W ResErr ; Clear the error flag if open MOVE.L A4, A0 ; Get the map handle <05sep85> BBM _DisposHandle ; and deallocate it. Map already exists. ; DisposHandle returns D0=0, signal already open. RTS ; D6=refnum of already opened file ; The file exists. ; Check size; if not null, load map & set up handles. @1 _GetEOF ; Get the EOF of the resource fork. MOVE.W #EOFErr, ResErr ; Assume EOF error (null fork) TST.L IOLEOF(A0) ; Is it a null fork? BEQ NMFail ; If so, close and fail--no map to load. CSS MOVEQ #HdrSize+PreSize,D0 ; byte count=HdrSize <11jul85> BBM MOVE.L (A4), A1 ; dereference map handle to ptr. <05sep85> BBM MOVE.L A1, D1 ; Copy to D1 for RdData MOVEQ #0, D2 ; Start at beginning of file BSR RdData ; Read data, set new ResErr result. BMI NMFail ; If failed, return error+close file. CSS MOVEA.L A1,A0 ; Source for blockmove <20jun85> BBM ADDA.L #HdrSize,A0 ; ... finish calc for source LEA HSCache,A1 ; Destination for blockmove MOVE.L #PreSize,D0 ; size for blockmove <11jul85> BBM _BlockMoveData ; move the key data to the stack MOVEA.L A0,A1 ; restore A1 SUBA.L #HdrSize,A1 ; ... finish restoring A1 BSR PreFormat ; check the preload format of this file CSS MOVEQ #HdrSize-4, D1 ; Get header size - 4 in D1 <19sep85> BBM MOVE.L ResMapOffset(A1), D2 ; Get offset to resource map, ADD.L D1, D2 ; but skip header MOVE.L MapSize(A1), D4 ; Get mapsize MOVE.L D4, D0 ; Get map size in D0 MOVE.L A4, A0 ; Get handle in A0 for size set <05sep85> BBM _SetHandleSize ; Set size to mapsize MOVE.W D0, ResErr ; return the error code in ResErr BNE.S NMFail ; If mem full, return error+close file. MOVE.L (A4), A1 ; Dereference new map <05sep85> BBM ; we are about to read in the extended attributes CLR.B mInMemoryAttr(a1) ; clear run-time-only attributes stb MOVE.L D4, D0 ; Get mapsize in D0 to calc bytes to read SUB.L D1, D0 ; MapSize-HeaderSize=bytes to read ADD.L A1, D1 ; skip header in buffer too BSR RdData ; Read in the bytes! BMI.S NMFail ; if IO err, return and close file. TST.L HSCache ; if already zero, then old format <19sep85> BBM BEQ.S @2 ; so skip check for new format <19sep85> BBM MOVE.L MapSize(A1),HSCache ; get second key (stored in mapsize) <19sep85> BBM BSR.S PreFormat ; check if new format <19sep85> BBM @2 MOVE.L D4,MapSize(A1) ; restore true map size <19sep85> BBM BSR CheckMap ; is the map in a consistent state <29apr85> BBM BMI.S NMFail ; ... if not, return and close file. ; Clear the overrideNextMapBit, twoDeepBit, and dontCountOrIndexDuplicatesBit ; Clear the preventMapFromClosingBit as well. These bits should be cleared when ; a new map is first created and only set after the appropriate Resource overrides ; calls have been made. andi.b #kDecompressionPasswordMask,mInMemoryAttr(a1) ; Successful load. Return with D6=refnum of file and D0=1 for "newmap" flag CLR.L MNext(A1) ; Zero nextMap handle MOVE.W D6, MRefNum(A1) ; Save refnum of file in map MOVEQ #1, D0 ; Return 1 for "new resource" flag RTS ; ...and return, successful open. ; error results: close the opened file, if necessary, dispose of the map ; handle if necessary, and return with D6=D0=-1. NMFail BSR SetFileIO ; Set up file frame again. D3=iorefnum. _Close ; Close the file NMNoFile MOVE.L A4, A0 ; Get the map handle <05sep85> BBM _DisposHandle ; ...and dispose of it. NMNoHandle CLR.L HSCache ; invalidate superpreload <20jun85> BBM CLR.L HSCHandle ; invalidate cache <20jun85> BBM MOVEQ #-1, D6 ; set D6=-1 for failure MOVEQ #-1, D0 ; Return -1 for failed open flag RTS ; return to InitResources or OpenResource. ;_______________________________________________________________________________ ; ; Routine: PreFormat (Utility) ; ; Arguments: HSCache (io.L) input = value to test; output = zero or key ; ; Preserved: A0-A7,D1-D7 ; Trashes: D0 ; ; Called by: NewMap ; Calls: NONE ; ; Function: Check to see if the key info agrees with the map header info. <21jun85> BBM ; This is done by checking if HSCache=$20B7A185. If not, clear ; HSCache, as that invalidates superpreload. ;_______________________________________________________________________________ PreFormat MOVE.L HSCache,D0 ; get the current key <21jun85> BBM SUB.L #PreKey,D0 ; check to see if key is present BEQ.S @9 ; key valid, jump to return CLR.L HSCache ; invalidate superpreload @9 CLR.L HSCHandle ; invalidate cache and clear out version# <11jul85> BBM RTS ;_______________________________________________________________________________ ; ; Routine: PROCEDURE RsrcZoneInit; ; ; Arguments: NONE ; ; Called By: A-trap through Dispatcher ; Calls: StdEntry, CloseFiles, GetEntries, StdZeroExit ; ; Function: Zeroes all handles in the system map which point to the ; application zone, and closes all other maps. This routine is ; called from the Memory Manager when an application zone is ; initialized. ;_______________________________________________________________________________ RsrcZoneInit BSR StdZEntry ; Link A6, save regs <09jul85> BBM TST.W SysMap ; Is there at least the system map? BMI.S @9 ; If not, just return, otherwise movem.l a0-a2/d0-d2,-(sp) ; help the compiler out a litle move.l ApplZone,a0 ; the zone in question cmp.l bufPtr,a0 ; Does this zonePtr = bufPtr? (Special Boot3.a case) beq.s @noTrash ; -> Yes, do not call TrashZone on the bogus zone move.w #10,d0 ; TrashZone ;_FigmentDispatch ; let everyone know this zone is gone dc.w $a0a4 @noTrash movem.l (sp)+,a0-a2/d0-d2 bsr FlushResourceCache ; CSS Flush the cache first ; Now make the system map forget about resources it has loaded into the ; application heap by clearing their handle locations. BSR.S CloseFiles ; Close all res files except system. move.l ResourceMgrStack.OverrideSysMapHndl(a6),d0 ; Start with the override map @mapLoop MOVE.L D0,A4 JSR GetRsrcCnt ; Skip to the entries <19jul85> BBM BMI.S @nextMap ; If no entries, no handles to zero. MOVE.L SysZone,A0 ; <32> MOVE.L bkLim(A0),D7 ; <32> Keep upper limit of System heap MOVE.L A0,D6 ; <32> Keep lower limit of System heap @unloadLoop MOVE.L RHndl(A2),A0 ; <22> Get resource handle CMP.L A0,D6 ; <32> Compare against lower bound of System zone BGT.S @clearReference ; <32> If d6 > a0, handle is not in heap, so clear it CMP.L A0,D7 ; <32> Compare resource against upper limit of System zone BGT.S @entryInSysHeap ; <32> If d7 > a0, handle is in System heap, so donÕt clear the reference out. @clearReference CLR.L RHndl(A2) ; Forget the disposed handle in app. heap. @entryInSysHeap ADD.W #RESize,A2 ; Otherwise skip to the next entry <19jul85> BBM DBRA D4,@unloadLoop ; If there is another entry, loop back @nextMap MOVE.L (A4),A4 MOVE.L mNext(A4),D0 ; Get the next map BNZ.S @mapLoop @9 BRA StdZeroExit ; ...and exit. ;_______________________________________________________________________________ ; ; Routine: CloseFiles (Utility) ; ; Arguments: None? ; ; Called by: RsrcZoneInit, CloseResFiles ; Calls: _CloseResFile ; ; Function: Closes all maps except the system [override] map. ;_______________________________________________________________________________ CloseFiles movem.l a0-a1/d0-d2,-(sp) ; save reg's cause GetOverrideMap destroys d1 & d2 @1 MOVE.L TopMapHndl, A0 ; Get the top map CMPA.L ResourceMgrStack.OverrideSysMapHndl(a6), A0 ; Is the current map the SYS map? CSS BEQ.S @9 ; if so, just exit ; eliminated special checks for rom map here <22jul85> BBM MOVE.L (A0), A0 ; Dereference map handle MOVE.W MRefNum(A0), -(SP) ; Push the map refnum _CloseResFile ; Close the resource file. BRA.S @1 ; and loop back. CSS @9 movem.l (sp)+,a0-a1/d0-d2 RTS ; ;_______________________________________________________________________________ ; ; Routine: ORFCommon (Utility) ; ; Arguments: A1 (input.L) pointer to resource file name ; A0 (input.L) pointer to the I/O block ; D0 (output.W) Error code ; D6 (output.W) IORefnum of File ; ; Called by: NewMap, CreateResFile ; Calls: _OpenRF ; ; Function: Open the resource fork whose name is in A1. A0 must point to ; the I/O block, usually allocated by SetFileIO. Returns Error ; code in D0/ResErr, and IORefNum in D6. ; ; First check to see if it is coming from the old .print driver. ; If it is, set the IOVRefNum to the BootDrive. ;_______________________________________________________________________________ ORFCommon ; rewritten for OpenRFPerm <05sep85> BBM ; This old code checked for the .Print driver open case by turning the pointer into a ; handle with RecoverHandle and subsequently calling GetResInfo to see if it was STR ; $E000. This causes a crash when passing pointers to strings in resouce handles. To ; avoid this, the new code checks for the .Print driver by getting the STR $E000 ; resource (with SetResLoad(false)) and comparing it with the file name pointer that ; was passed. move.l a0,-(sp) ; save pointer to parameter block move.w CurMap,-(sp) ; save the current map move.b ResLoad,-(sp) ; save the old value for whether to load resources move.w ResourceMgrStack.OverrideSysMap(a6),CurMap ; get the resource from the system file sf ResLoad ; donÕt load the resource subq #4,sp ; make room for resource handle move.w #$E000,-(sp) ; get that resource handle _GetString ; got the string now! move.l (sp)+,d0 ; get the string into a register move.b (sp)+,ResLoad ; restore ResLoad move.w (sp)+,CurMap ; restore CurMap move.l (sp)+,a0 ; get back the parameter block pointer tst.l d0 ; check if the handle is nil bz.s @notPrint ; nope, it is not the printer driver name exg d0,a1 ; move to address register for dereference move.l (a1),a1 ; dereference to get the pointer exg d0,a1 ; move file name pointer back to A1 cmp.l d0,a1 ; check and see if it is the printer name bne.s @notPrint ; nope, it is not the printer driver ; Note that we can get here if there is a STR $E000 that has not yet been ; loaded and the file name pointer in A1 is NIL! This is not a problem, ; since a NIL file name pointer is illegal anyway, and changing the vRefNum ; in the parameter block for OpenRF shouldnÕt have any effect. move.w BootDrive,ioVRefNum(a0) ; always open the printer driver on the boot drive @notPrint MOVE.L A1,IOFileName(A0) ; Set filename pointer CLR.L IOOwnBuf(A0) ; No buffer _OpenRF ,newHFS ; HFSOpen the file's resource fork MOVE.W IORefNum(A0),D6 ; set D6=file refnum. MOVE.W D0, ResErr ; and set ResErr RTS ;_______________________________________________________________________________ ; ; Routine: PROCEDURE HCreateResFile(vRefNum: INTEGER; dirID: LONGINT; fileName: Str255); ; ; Called By: A-trap through dispatcher. ; ; Function: ; Initialize a null resource fork for the given filename ; In the specified directory and volume. ; ; From ResourceMgrPatches.a ;_______________________________________________________________________________ ; MyStkFrame Record 0 A6Link ds.l 1 Return ds.l 1 filename ds.l 1 dirID ds.l 1 vRefNum ds.w 1 EndR HCreateResFile With MyStkFrame BSR StdZEntry ; Link and save regs MOVE.L $00(A0), A1 ; Get filename pointer BSR SetFileIODirID ; Set up the file IO frame A0 --> move.w vRefNum(a6),ioVRefNum(a0) ; stuff vRefNum into parameter block move.l dirID(a6),ioDirID(a0) ; stuff the ioDirID into parameter block ENDWITH BSR.S ORFCommon ; Attempt to open the resource fork. ; D6 := refnum of file. BEQ.S @1 ; If successful, see if the fork is null. CMP.W #FNFErr, D0 ; Was the error "file not found"? BNE.S @9 ; If a different error, can't handle, else ;Roll in NewCreate from ResourceMgrExtensions.a _Create ,newHFS ; HFScreate a new file with null D+R forks MOVE.W D0,ResErr ; ... else (A0) points to parameter block <27feb85> BBM BMI.S @9 ; ... and error exit BSR.S ORFCommon ; and attempt to open again. D6=refnum. BMI.S @9 ; If open failed, can't do anything. @1 _GetEOF ; Get EOF of rsrc fork. (file exists!) MOVE.W #DupFNErr, ResErr ; Assume error, fork already exists TST.L IOLEOF(A0) ; Is it a null fork, ready to initialize? BNE.S @7 ; If not, leave DupFNErr and exit, else MOVEQ #HdrSize, D0 ; Write header only at 0. LEA NullRF, A1 MOVE.L A1, D1 ; Set buffer address to null map BSR WrDataSt ; Write out initial map @0. Set ResErr. MOVEQ #NullRMSize, D0 ; Set number of bytes MOVEQ #64, D2 ; Get 64 for offset... ASL.W #2, D2 ; left shift 2 for 256=FirstResData. BSR WrData ; Write out initial map. Set ResErr. @7 _Close ; Close the file. Error code in D0 ignored... ; WrData, WrDataSt preserved A0. @9 jmp StdTenExit ; clear the dirID and exit (done by StdExit on newer ROMs) ;_______________________________________________________________________________ ; ; Routine: PROCEDURE CreateResFile(fileName: Str255); ; ; Arguments: 8(A6), A0 pointer to filename ; ; Called By: A-trap through dispatcher. ; Calls: StdEntry, SetFileIO, ORFCommon, _Create, _GetEOF, WrDataSt, ; WrData, _Close, StdFourExit ; Function: ; Initialize a null resource fork for the given filename. ; If the file does not exist at all, create it. ; note: ; <27feb85> BBM added check to see if file ;_______________________________________________________________________________ CreateResFile BSR StdZEntry ; Link and save regs <09jul85> BBM MOVE.L (A0), A1 ; Get filename pointer BSR SetFileIODirID ; Set up the file IO frame A0 --> BSR.S ORFCommon ; Attempt to open the resource fork. ; D6 := refnum of file. BEQ.S @1 ; If successful, see if the fork is null. CMP.W #FNFErr, D0 ; Was the error "file not found"? BNE.S @9 ; If a different error, can't handle, else _Create ; create a new file with null D+R forks MOVE.W D0,ResErr ; ... else (A0) points to parameter block <27feb85> BBM BMI.S @9 ; ... and error exit BSR.S ORFCommon ; and attempt to open again. D6=refnum. BMI.S @9 ; If open failed, can't do anything. @1 _GetEOF ; Get EOF of rsrc fork. (file exists!) MOVE.W #DupFNErr, ResErr ; Assume error, fork already exists TST.L IOLEOF(A0) ; Is it a null fork, ready to initialize? BNE.S @7 ; If not, leave DupFNErr and exit, else MOVEQ #HdrSize, D0 ; Write header only at 0. LEA NullRF, A1 MOVE.L A1, D1 ; Set buffer address to null map BSR WrDataSt ; Write out initial map @0. Set ResErr. MOVEQ #NullRMSize, D0 ; Set number of bytes MOVEQ #64, D2 ; Get 64 for offset... ASL.W #2, D2 ; left shift 2 for 256=FirstResData. BSR WrData ; Write out initial map. Set ResErr. @7 _Close ; Close the file. Error code in D0 ignored... ; WrData, WrDataSt preserved A0. @9 BRA StdFourExit ; pop 4 bytes and exit ;_______________________________________________________________________________ ; ; Routine: FUNCTION HOpenResFile(vRefNum: INTEGER; dirID: LONGINT; fileName: ; Str255; permission: SignedByte): INTEGER; ; ; Function: Given filename, opens this resource. Returns resource file ; reference number. If the file was already open, returns the ; current refnum of the file. If negative, an error occurred and ; the code can be noted in ResErr. InitResources must be called ; before OpenResFile. Sets ResLoad to TRUE initially. ; From ResourceMgrPatches.a ;_______________________________________________________________________________ WITH ResourceMgrStack HOpenResFile BSR StdZEntry ; Link and save regs MOVE.W $0a(a0),ioBlock+IOVRefNum(A6) ; stuff vRefNum into ioParmBlk MOVE.L $06(a0),ioBlock+ioDirID(A6) ; Stuff dirID into ioParmBlk MOVE.L $02(a0),A1 ; Get fileName in A1 for call to NewMap MOVE.B $00(a0),ioBlock+ioPermssn(a6) ; set up permission byte BSR OPResFileCommon ; go open the file. MOVE.W D6,20(a6) ; output refNumÉ @9 BRA StdTwelveExit ; clear the dirID and exit (done by StdExit on newer ROMs) ENDWITH ;_______________________________________________________________________________ ; ; Routine: FUNCTION OpenResFile(fileName: Str255): INTEGER; ; ; Arguments: 8(A6),A0 (input) pointer to filename ; 12(A6) (output.x) Resource file refnum. ; ; Called By: (OpenResFile): A-trap through Dispatcher ; (OPResFile): OpenRFPerm ; Calls: StdEntry, NewMap, PreLoad2, StdFourExit ; ; Function: Given filename, opens this resource. Returns resource file ; reference number. If the file was already open, returns the ; current refnum of the file. If negative, an error occurred and ; the code can be noted in ResErr. InitResources must be called ; before OpenResFile. Sets ResLoad to TRUE initially. ; note: ; <22Jan85> BBM We want to call PreLoad, but we don't want to set ResLoad flag, ; so we call PreLoad2. This fix was part of the ram patches to ; the version 7.0 ROM. ;_______________________________________________________________________________ OpenResFile ;„„„„ Fix for the old AppleTalk ImageWriter and LQ AppleTalk ImageWriter until these drivers are fixed move.b ResLoad,-(sp) ; save the old value for whether to load resources sf ResLoad ; donÕt load the resource subq #4,sp ; make room for resource handle move.w #$E000,-(sp) ; get that resource handle _GetString ; got the string now! move.l (sp)+,d0 ; get the string into a register move.b (sp)+,ResLoad ; restore ResLoad tst.l d0 ; check if the handle is nil bz.s NotForPrinting ; nope, it is not the printer driver name exg d0,a0 ; move to address register for dereference move.l (a0),a0 ; dereference to get the pointer exg d0,a0 ; move file name pointer back to A1 cmp.l 4(sp), d0 ; check and see if it is the printer name bne.s NotForPrinting ; nope, it is not the printer driver movem.l d1-d2/a1,-(sp) ; Resource Mgr calls shouldnÕt touch these move.l #$D8000000,-(SP) ; PrLoadDriver _PrGlue ; Call PrGlue CSS movem.l (sp)+,d1-d2/a1 ; restore registers <4> move.w D0, ResErr ; copy the error result into ResErr move.w $952, D0 ; copy the printing refnum into the function result ; This will be the error from HOpenResFile if it didn't work. move.l (sp)+, a0 ; save return address add.l #4, sp ; strip the parameter move.w d0, (sp) ; set the function result jmp (a0) ; out of here NotForPrinting ; ;„„„ end fix BSR StdZEntry ; Link A6, save regs <30oct85> BBM MOVE.L (A0), A1 ; Get name pointer in A1 BSR OPResFileCommon ; go open the file. move.w d6,12(a6) ; output refNumÉ BRA StdFourExit ; ...and exit ;_______________________________________________________________________________ ; ; Routine: FUNCTION OpenRFPerm(fileName:Str255, VRefNum: INTEGER, ; Permission: Byte): INTEGER; ; Arguments: ???????? ; ; Called By: A-trap through Dispatcher ; Calls: StdZEntry, OPResFile ; ; Function: Given filename, volume reference number and permissions, open ; this resource. Returns resource file reference number. If the ; file was already open, returns the current refnum of the file. ; If negative, an error occurred and the code can be noted in ; ResErr. InitResources must be called before OpenResFile. ;_______________________________________________________________________________ ROMOpenRFPerm OpenRFPerm ; new routine BSR StdZEntry ; Save regs etc. (D0 saved across call) WITH ResourceMgrStack MOVE.W $02(a0),ioBlock+IOVRefNum(A6) ; stuff vRefNum into ioParmBlk MOVE.L $04(a0),A1 ; Get fileName in A1 for call to NewMap MOVE.B $00(a0),ioBlock+ioPermssn(a6) ; set up permission byte BSR OPResFileCommon ; go open the file. ENDWITH move.w d6,16(a6) ; output refNumÉ BRA StdEightExit ; and go to common code <05sep85> BBM ;_______________________________________________________________________________ ; ; Routine: OPResFileCommon ; Arguments: A1 - Ptr to file name of resource fork to openÉ ; ; Called By: HOpenResFile, OpenResFile, and OpenRFPerm ; Calls: NewMap, PreLoad2 ; ; A1 points to name to open at this point and permissions and DirID are set ; in the pb on the stack. ; ; return refNum in D6 OPResFileCommon MOVE.L MinusOne,LastSPExtra ; invalidate font cache BSR NewMap ; D0=dirID, D3=refnum, A1=map ptr, A2 is map handle MOVE.W D6,-(sp) ; Return refnum of map, or -1 for error. (save refNum on the stack) BMI.S @9 ; If I/O error, return. MOVE.W D6, curMap ; Save it as current map. TST.W D0 ; Was it a newly-created map? BEQ.S @9 ; No, it was already there, don't relink. MOVE.L TopMapHndl, MNext(A1) ; If new, link. Store old top as next map MOVE.L A4,TopMapHndl ; Set new map as top map <05sep85> BBM BSR PreLoad2 ; Preload required resources... <22Jan85> BBM BSR CheckAndFlushFontCache ; If this new file has fonts we should flush the font cacheÉ @9 move.w (sp)+,d6 ; get the ref num to return rts ; exit ;_______________________________________________________________________________ ; ; Routine: PROCEDURE UseResFile(RefNum: INTEGER); ; ; Arguments: 4(SP) (input) resource file refnum ; ; Called By: A-trap through dispatcher ; Calls: StdMapEntry, StdTwoExit ; ; Function: Given refnum, sets current resource to use. If there isn't any ; such map, ignores the request. ;_______________________________________________________________________________ UseResFile ; We have to check for UseResFile(0) first because this is the one case where ; we don't want the override of the system to come back in d6 but instead we want ; to have the real SysMap in d6. BSR StdZEntry ; Link and save regs <12aug85> BBM MOVE.W (A0), D6 ; Get the resource map refnum bne.s @notSystemMap move.w SysMap,d6 ; 0 means use SysMap bra.s @exit @notSystemMap BSR GetMap ; Scan for it BMI.S @err ; If not found, exit, otherwise @exit MOVE.W D6, CurMap ; Set this refnum as the current map CLR.W ResourceMgrStack.doOverrides(a6); Turn off overrides so that the CurMap doesn't get overwritten. CSS BRA StdTwoExit ; and exit. @err MOVE.W #ResFNotFound, ResErr ; set error code, and BRA StdTwoExit ; and exit. ;_______________________________________________________________________________ ; ; Routine: FUNCTION GetResFileAttrs(refnum: INTEGER): INTEGER; ; ; Arguments: 8(A6) (input.W) Resource file refnum ; 10(A6) (output.B) Attribute byte ; ; Called By: A-trap through dispatcher ; Calls: StdMapEntry, StdTwoExit ; ; Function: Given a resource file, return its attribute byte in low order. ; high order is trash. ;_______________________________________________________________________________ GetResFileAttrs BSR.S StdMapEntry ; Look for the file. If not there, exit MOVE.B MAttr(A3),11(A6) ; Return the byte in low order BRA StdTwoExit ; and exit. ;_______________________________________________________________________________ ; ; Routine: PROCEDURE SetResFileAttrs(refnum: INTEGER; attrs: INTEGER); ; ; Arguments: 10(A6) (input.W) resource file refnum ; 8(A6) (input.W) Resource attribute byte) ; ; Called By: A-trap through dispatcher ; Calls: StdEntry, GetMap, StdFourExit ; ; Function: Given a resource file, set its attribute byte. ; note: ; there is no error checking!! The attribute bytes could be wrong ; and this procedure will still write them out. ;_______________________________________________________________________________ SetResFileAttrs BSR StdZEntry ; Look for the file. If not there, exit <12aug85> BBM MOVE.W 10(A6), D6 ; Get the refnum BSR GetMap ; Get the corresponding map BMI.S @1 ; if can't find, just exit. MOVE.B 9(A6), MAttr(A3) ; Set attributes word @1 BRA StdFourExit ; and exit. ;_______________________________________________________________________________ ; ; Routine: StdMapEntry (utility) ; ; Arguments: 8(A6) (input.W) Map refnum ; D6 (output.W) Map refnum ; ; Called By: UseResFile, UpdateResFile, CloseResFile ; Calls: StdEntry, GetMap, StdTwoExit ; ; Function: Given the map refnum 8(A6), scans for the map and exits if not ; found. StdEntry returns A0=8(A6), so the refnum is copied from ; (A0). Callers must have a two-byte argument. ;_______________________________________________________________________________ StdMapEntry MOVE.L (SP)+, D0 ; Save return address in D0 BSR StdZEntry ; Link and save regs <12aug85> BBM MOVE.L D0, -(SP) ; Restore return address MOVE.W (A0), D6 ; Get the resource map refnum BSR GetMap ; Scan for it BMI.S @1 ; If not found, exit, otherwise RTS ; just return. @1 ADDQ #4, SP ; pop return address, MOVE.W #ResFNotFound, ResErr ; set error code, and BRA StdTwoExit ; and exit. ;_______________________________________________________________________________ ; ; Routine: FirstRes, NextRes, ZfirstRes, ZnextRes (utilities) ; ; Arguments: A2 (input.L) Pointer to last rsrc (used by NextRes) ; A4 (input.L) map handle ; D1 (input.L) which bit to test in RAttr(A2) ; A2 (output.L) Pointer to the resource entry ; D0 (output.L) Next file Location ; ; Unchanged: A0-A1,A3-A7,D1-D7 ; Trashed: None ; ; Called By: (FirstRes): PreLoad, PreLoad2,UpdateResFile ; (NextRes): PreLoad, PreLoad2,UpdateResFile ; Calls: GetRsrcCnt ; ; Function: FirstRes and NextResŹare File-Order routines. They are used to ; find the first/next resource in file order. D1 determines what ; kind of search to do. If (D1.W < 0) then FirstRes/NextRes will ; find the first/next resource in file order. If (D1.W > 0) then ; FirstRes/NextRes will test RAttr(A2) with bit referenced in D1. ; In other words if (D1.W > 0) then FirstRes/NextRes will find ; the first/next resource in file order with that bit set. ; FirstRes/NextRes point A2 to the entry found and sets CC=EQ. If ; no entry was found A2 is garbage, and CC=MI. Alternate entries ; ZfirstRes and ZnextRes force search through all rsrcs. ;_______________________________________________________________________________ ZfirstRes MOVEQ #-1,D1 ; get the first resource in file order <03oct89 bpa> FirstRes MOVEQ #-1, D0 ; prime with -1 for first resource BRA.S FNCmn ; and jump to common code ZnextRes MOVEQ #-1,D1 ; get the very next resource <03oct89 bpa> NextRes MOVE.L RLocn(A2), D0 ; Get the location AND.L Lo3Bytes,D0 ; and mask off the high byte. FNCmn ; (only FirstRes uses this label) MOVEM.L A3/D2-D7,-(SP) ; Save regs MOVE.L D0, D2 ; Copy location to find successor of BSR GetRsrcCnt ; Point to the first entry <10may85> BBM BMI.S @9 ; If none, exit LEA MinusOne,A3 ; Point to MinusOne, but <26aug85> BBM SUBQ.L #RLocn,A3 ; skip back RLocn. (RLocn(A2)=MinusOne). MOVE.L A3,D6 ; D6=new candidate. valid A2 will replace. MOVEQ #-1, D7 ; D7:=FFFFFFFF LSR.L #1, D7 ; shift rt by 1 = 7FFFFFFF, +ve infinity. TST.W D1 ; if (D1 < 0) then get next in file order <03oct89 bpa> BMI.S @3 ; ... else fall through to test bit loop <03oct89 bpa> @1 BTST D1,RAttr(A2) ; if you don't want to preload this one, <10may85> BBM BEQ.S @2 ; ... then don't look at it. MOVE.L RLocn(A2), D0 ; Get the resource location AND.L Lo3Bytes,D0 ; AND off high order 8 bits CMP.L D0, D2 ; is this location greater than given? BGE.S @2 ; No, try next CMP.L D0, D7 ; is it less than the last candidate? BLE.S @2 ; no, old candidate is still good MOVE.L D0, D7 ; else replace old candidate with new MOVE.L A2, D6 ; Save A2 candidate also in D6 @2 ADD.W #RESize,A2 ; point to the next entry DBRA D4,@1 ; if there was one, loop back BRA.S @8 ; ... else goto exit code. @3 MOVE.L RLocn(A2), D0 ; Get the resource location <13may85> BBM AND.L Lo3Bytes,D0 ; AND off high order 8 bits CMP.L D0, D2 ; is this location greater than given? BGE.S @4 ; No, try next CMP.L D0, D7 ; is it less than the last candidate? BLE.S @4 ; no, old candidate is still good MOVE.L D0, D7 ; else replace old candidate with new MOVE.L A2, D6 ; Save A2 candidate also in D6 @4 ADD.W #RESize,A2 ; point to the next entry DBRA D4,@3 ; if more loop back, else fall into exit code @8 MOVE.L D6,A2 ; return A2 as the next resource entry MOVE.L D7,D0 ; Return D0 as the next file Location MOVE.L RLocn(A2),D7 ; Get this entry's location. AND.L Lo3Bytes,D7 ; and off high bits. CMP.L D0,D7 ; Set CC's. EQ=valid entry, MI=end of list. @9 MOVEM.L (SP)+,A3/D2-D7 ; Restore regs RTS ; ...and return. ;_______________________________________________________________________________ ; ; Routine: PROCEDURE UpdateResFile(refNum: INTEGER); ; ; Arguments: 8(A6) (input.W) resource file refnum ; ; Called By: A-trap through dispatcher ; Calls: StdMapEntry, ResRW, StdTwoExit, SetRFEOF, FirstRes, WrRsrc, ; NextRes, CheckLoad, _ReleaseResource, SizeRes, WrData, WrDataSt ; ClearIgnore ; Labels: UpdateResFile, UpDateCompact, WriteMap ; ; Function: Given refnum, writes out new resources and updates map. If ; refnum=0, use system file. CloseResFile calls UpdateResFile, ; so on exit from an application all resource files which are ; marked dirty have thier maps writen out and are compacted. ; ; The new UpdateResFile (July 85) uses one buffer to do all the ; reads and writes. When compacting the file the regester usage ; is as follows: ; A1 end of the region already compacted and still in buffer. ; A2 pointer to Resource entry. ; A3 handle to the start of locked update buffer. ; A4 handle to resource map. ; D3 pointer to the end of the update buffer. ; D5 current Read position in the file less ResDataOffset. ; D6 current resource file refnum. ; D7 current Write position in the file less ResDataOffset. ;_______________________________________________________________________________ UpdateResFile WITH ResourceMgrStack move.l ExpandMem,a0 ; move.b ExpandMemRec.emScanOverrideMaps(a0),D0 ; save override state. (StdZEntry must preserve d0) clr.b ExpandMemRec.emScanOverrideMaps(a0) ; turn it off for StdEntry BSR StdZEntry ; Link and save regs <12aug85> BBM MOVE.W (A0), D6 ; Get the resource map refnum move.l ExpandMem,a0 ; move.b d0,ExpandMemRec.emScanOverrideMaps(a0) ; restore override state BSR GetMap ; Scan for it BMI.S @ErrExit ; If not found, exit, otherwise clr.w ResErr ; start out freshÉ BSR UpdateResFileCommon ; first try updating this resfileÉ tst.w ResErr ; Did we get the first file? bra.s @exit ; no wayÉ get outta here! subq #4,sp move.l a4,-(sp) _GetOverrideMap ; See if thereÕs an override map for this file move.l (sp)+,a3 ; Get the map ; Check to see if weÕre updating the system file, or just another file. If weÕre updating the ; system file, then make sure we update all the font files too. If itÕs just a generic resource map, ; update just itÕs override maps and the file itself. ; ; Note: I know that explicitly updating an override map of the system wonÕt update the ; font files. I think this is the right behaviour, since anyone that is referencing ; the override map explicitly probably has something specific in mind. cmp.l SysMap(a6),a4 ; If weÕre updating the system file, then update the font files too bne.s @notUpdatingSystemFile ; This is done by setting a4 to nil, so that the loop wonÕt end until moveq #0,a4 ; the end of the chain is reached bra.s @updateOverrideMaps ; ItÕs not the system file. @notUpdatingSystemFile cmp.l a3,a4 ; If the file didnÕt have any override maps beq.s @exit ; Just update the original. ; Update any changed override maps for this file. @updateOverrideMaps move.l a4,-(sp) ; save a4 move.l a3,a4 ; get map to try in a4 bsr UpdateResFileCommon ; Try updating this mapÉ move.l (sp)+,a4 ; restore a4 move.l (a3),a0 ; Dereference the map handle again @nextMap move.l mNext(a0),d0 ; Get the next resource map handle cmp.l d0,a4 ; Is the next map the original map? beq.s @exit ; Yep. End the loop and fall through to UpdateResFile for the final time move.l d0,a3 ; Otherwise, update the next one if needed bra.s @updateOverrideMaps ; Update the original file @ErrExit MOVE.W #ResFNotFound,ResErr ; resource file not found error @exit bsr FlushResourceCache ; from UpdateResourceOverrideFile bra StdTwoExit ENDWITH ; UpdateResFileCommon takes a map in A4 and tries to update itÉ ; it preserves a0-a4/d0-d1 UpdateResFileCommon movem.l a0-a4/d0-d1,-(sp) ; save regs BSR ResRW ; Read/write allowed for this resFile? BEQ.S @1 ; yes, go on <16apr85> BBM MOVE.W #mapReadErr,ResErr ; ... else don't allow write, mark as error BRA UpdateResExit ; ... and exit always <03jul85> BBM @1 BTST #MapChanged,MAttr(A0) ; Map changed? (***Hack!, should be MapUpdate) BEQ UpdateResExit ; if not don't bother to update BSR SetRFEOF ; Check disk full even though might compact <28jan85> BBM BMI UpdateResExit ; if failed return error BCLR #MapCompact, MAttr(A3) ; Do I need to compact? <12jun85> BBM BNE.S UpdateCompact ; If so, skip to compact stuff MOVEQ #ResChanged,D1 ; which bit to check in FirstRes/NextRes <09apr85> BBM BSR FirstRes ; first resource in file order that changed <13may85> BBM BMI.S @4 ; If none, go on. <03jul85> BBM @0 BSR WrRsrc ; otherwise write out the changed resource. <09apr85> BBM BSR NextRes ; next in file order (NOTE D1=ResChanged still) <13may85> BBM BEQ.S @0 ; and loop back, if any left. @4 BRA WriteMap ; and go write map if necc. <12jun85> BBM UpDateCompact ; this section does a buffer update <12jun85> BBM BSR ZfirstRes ; get the first resource in file order <04jun85> BBM BMI WriteMap ; if none, go on. <12jun85> BBM MOVE.L (A4),A0 ; Dereference map handle <10oct85> BBM MOVE.L ResDataOffset(A0),D7 ; D7 will point to current write position <09oct85> BBM SUB.L ResMapOffset(A0),D7 ; Do we need to compress this file? <09oct85> BBM BCS.S @2 ; Compact to ResDataOffset <10oct85> BBM BSR GetRsrcCnt ; set up indexing for looping <10oct85> BBM @1 ADD.L D7,RLocn(A2) ; Add in new resDataOffset <10oct85> BBM ADD.W #RESize,A2 ; point to the next resource <10oct85> BBM DBRA D4,@1 ; loop back through entire map <10oct85> BBM MOVE.L ResMapOffset(A0),ResDataOffset(A0) ; make new resDataOffset <10oct85> BBM BSR ZfirstRes ; get the first resource in file order <10oct85> BBM @2 MOVEQ #0,D7 ; compact to the beginning of ResDataOffset <10oct85> BBM BRA.S stFindGap ; Check to see if first rsrc needs compaction <10oct85> BBM findGap BTST #ResChanged,RAttr(A2) ; Does this resource need to be written? BEQ.S @1 ; ... No, go get its size BSR WrRsrc ; ... else write out resource MOVE.L RHndl(A2),A0 ; What is the size of this resource? _GetHandleSize ; BRA.S @2 ; go check if time to start compact @1 BSR SizeRsrc ; Get the size of this resource @2 ADDQ.L #LenWdLen,D0 ; add in length size to size of resource (.L) <01jul85> BBM MOVE.L RLocn(A2),D7 ; D7 points to current position in file ADD.L D0,D7 ; point past this resource AND.L Lo3Bytes,D7 ; mask off RAttrs <13jun85> BBM BSR ZnextRes ; Get the next resource <02jul85> BBM BMI wrDtSize ; maybe only map needs to be moved up <09jan86> BBM stFindGap ; new label <10oct85> BBM MOVE.L D7,D0 ; need a 24 bit compare of RLocn(A2) & D7 <09oct85> BBM SUB.L RLocn(A2),D0 ; Compare this with the next file offset AND.L Lo3Bytes,D0 ; result is a 24 bit compare if EQ BEQ.S findGap ; don't start compact yet SUB.L (A4),A2 ; we make A2 an offset since map may move <29jun85> BBM BSR MaxRFEOF ; find how much space we need to use <09jan86> BBM MOVE.L D0,D3 ; Calculate how big this file is <09jan86> BBM _MaxBlock ; how much can we get? <09jan86> BBM CMP.L D3,D0 ; Get minimum of (filesize, maxblock) into D3 BGE.S @0 ; D3 already has the minimum EXG D3,D0 ; only if D0 and D3 are backwards @0 MOVEQ #64,D0 ; make sure we have a buffer size >= 1k <09jan86> BBM ASL.W #4,D0 ; D0 = $400 (or 1K) <09jan86> BBM CMP.L D0,D3 ; Is it greater than 1k? <09jan86> BBM BGE.S @1 ; CC=GE means we can get buffer in Zone <09jan86> BBM MOVE.L D0,D3 ; D3 will be a buffer of 1024k size <09jan86> BBM LINK A3,#-1024 ; Get 1k buffer and set up bogus MP for A3 <08jan86> BBM MOVE.L SP,(A3) ; A3 now points to a good MP <08jan86> BBM BRA.S @2 ; and don't try to lock down the stack <08jan86> BBM @1 MOVE.L D3,D0 ; D3 is size of update buffer <09jan86> BBM _NewHandle ; Get a handle to my update buffer <09jan86> BBM _Hlock ; Don't allow it to move and ruin my ptrs <08jan86> BBM MOVE.L A0,A3 ; A3 is our handle to update buffer @2 ADD.L (A4),A2 ; restore A2 to a pointer <08jan86> BBM MOVE.L (A3),D0 ; D0 now points to the beginning of buffer _StripAddress ; make sure no garbage in high byte ADD.L D0,D3 ; D3 now points to end of update buffer MOVE.L D0,A1 ; A1 is our compacted region pointer MOVE.L A1,D4 ; nothing is read in yet, so D4 = A1 <01jul85> BBM MOVE.L D7,D5 ; D5 = file read pos; D7 = file write pos FPvCmpFrm MOVE.L jCmpFrm,A0 ; get the vector from the OSJumptable <27oct85> BBM JMP (A0) ; and go to the routine <27oct85> BBM vCmpFrm ; Def to build dispatch entry <27oct85> BBM @3 BTST #ResChanged,RAttr(A2) ; is the rsrc in mem (and needs to be written) BEQ.S @4 ; CC=EQ means ResChanged bit not set BSR.S CmpFrmMem ; else get rsrc from memory and compact BPL.S @5 ; go get next resource <02jul85> BBM @4 BSR CmpFrmDsk ; read rsrc from disk and compact @5 BSR ZnextRes ; go get the next resource BEQ.S @3 ; if more resources loop back @6 MOVE.L A1,D0 ; empty the buffer of the remaining stuff SUB.L (A3),D0 ; ... now D0 has size left to write <10jul85> BBM _StripAddress ; ... just to be on the safe side MOVE.L (A3),D1 ; start of buffer address for write <10jul85> BBM MOVE.L (A4),A0 ; get current file write position MOVE.L D7,D2 ; ... get biased position ADD.L ResDataOffset(A0),D2 ; ... and take away the bias BSR WrData ; and write out the data left in buffer ADD.L D0,D7 ; point current write position past last rsrc MOVE.L (A3),A0 ; we don't need this buffer so get rid of it CSS CMPA.L SP,A0 ; CSS BEQ.S @7 ; CC=EQ means buffer is on stack CSS ; CSS This works because (A3) contains the SP at the ; time of creation if we created the buffer on the stack, ; AND the stack is the same depth here and at the time ; of creation. MOVE.L A3,A0 ; Else buffer is in memory <08jan86> BBM _DisposHandle ; get rid of it <08jan86> BBM BRA.S @8 ; and skip by stack code <08jan86> BBM @7 UNLK A3 ; Dispose of buffer on stack <08jan86> BBM @8 MOVE.L (A4),A3 ; Derefernce map to write out <08jan86> BBM wrDtSize ; New lable <10oct875> BBM MOVE.L D7,DataSize(A3) ; update current size for the data WriteMap BCLR #MapChanged, MAttr(A3) ; Clear the map-changed bit before write. BEQ.S UpdateResExit ; If the map didn't change either, exit. MOVE.L DataSize(A3), D2 ; Get updated data size ADD.L ResDataOffset(A3), D2 ; Add data offset to get new map offset MOVE.L D2, ResMapOffset(A3) ; Save new map offset from D2 MOVE.L MapSize(A3), D0 ; byte count=size of map MOVE.L A3, D1 ; Address of map in memory. D2=map offset. BSR WrData ; Write the map out! MOVEQ #HdrSize, D0 ; byte count=HdrSize (write new header!) <12jun85> BBM BSR WrDataSt ; ...and do it! BSR SetRFEOF ; Set new EOF UpdateResExit @9 movem.l (sp)+,a0-a4/d0-d1 rts ;_______________________________________________________________________________ ; ; Routine: CmpFrmMem (utility) ; ; Arguments: A1 (i/o.l) pointer to the end of compacted region ; A3 (input.l) Handle to start of update buffer ; A4 (input.l) current map handle ; D3 (input.l) pointer to end of update buffer ; D4 (i/o.l) pointer in buffer (end of stuff read in) ; D5 (i/o.l) current file read position - ResDataOffset ; D6 (input.w) the current file refnum ; D7 (i/o.l) current file write position - ResDataOffset ; RLocn(A2) (output.l) the new file offset for this rsrc ; ; Unchanged: A2-A7,D1,D3,D6 ; Trashed: A0,D0-D2 ; ; Called By: UpdateResFile ; Calls: _BlockMove, CmpctRead, _GetHandleSize, NotFound, PartWrite, ; Ptr1Exit, RLocnNew, WriteSize ; ; Function: Compacts resource from Memory (because the ResChanged bit set). ; Just does compact of one resource. If cann't read in all of ; resource into update buffer, writes out compacted stuff and ; continues until all is done. Also updates RLocn(A2) as well. ;_______________________________________________________________________________ CmpFrmMem BSR PartWrite ; make sure we have some room to play in MOVE.L RHndl(A2),A0 ; get info about resource _GetHandleSize ; TST.L D0 ; check to see if purged or zero length <02jul85> BBM BMI NotFound ; if purged exit with CC=MI or CC=EQ <10jul85> BBM BSR.S RLocnNew ; update new file position for this rsrc BSR.S WriteSize ; write size of this resource into buff <08jul85> BBM MOVE.L D0,D2 ; check to see if enough room in buff ADD.L A1,D2 ; ... D2 now points to proposed end CMP.L D2,D4 ; Does it fit inside read buffer? MOVE.L (A0),A0 ; dereference handle to rsrc for calc <10jul85> BBM BGE.S Ptr1Exit ; CC=GE means it fits so transfer and exit <10jul85> BBM MOVE.L D0,D2 ; D2 will be the number of bytes left in rsrc MOVEQ #0,D1 ; D1 will be offset into resource <02jul85> BBM @1 MOVE.L RHndl(A2),A0 ; set up A0 to be pointer into resource MOVE.L (A0),A0 ; ... dereference handle ADD.L D1,A0 ; ... and add in offset <02jul85> BBM MOVE.L D3,D0 ; How much room in update buffer? SUB.L A1,D0 ; ... D0 has free byte count in buffer CMP.L D2,D0 ; is there room in buffer? BGE.S @7 ; CC=GE means enough room <02jul85> BBM ADD.L D0,D1 ; update offset into resource <02jul85> BBM SUB.L D0,D2 ; Update number of bytes left BSR.S @8 ; Transfer what we can <02jul85> BBM BSR PartWrite ; write out what we can BRA.S @1 ; and loop back for the rest of rsrc @7 MOVE.L D2,D0 ; D2 has number of bytes left in rsrc @8 MOVE.L A1,D4 ; update buffer end read pointer <02jul85> BBM ; BRA.S Ptr1Exit ; and exit with block move stuff <10jul85> BBM ; *!*!*!* Heads Up - Falling Through ; BRA commented out for warning free assembly. ;_______________________________________________________________________________ ; ; Routine: Ptr1Exit, Ptr2Exit, Ptr3Exit (utilities) <10jul85> BBM ; ; Arguments: A0 (input.l) pointer to source of blockmove (Ptr1Exit) ; A1 (i/o.l) compacted region pointer ; D0 (input.l) size of blockmove or offset to add to D5/A1 ; D4 (output.l) end of region read into buffer ; D5 (i/o.l) current file read position ; ; Unchanged: A0,A1-A7,D0-D3,D5-D7 ; Trashed: none ; ; Called By: CmpFrmMem ; Calls: none ; ; Function: standard exit code for several routines. Saves a few bytes and ; makes sure a few tests are done. ; ; Warning: Entered by falling through from previous function (CmpFrmMem) ;_______________________________________________________________________________ Ptr1Exit CMP.L A0,A1 ; is the block move necessary? <10jul85> BBM BEQ.S Ptr2Exit ; ... no, then skip it MOVE.L D0,-(SP) ; save D0 across Blockmove call _BlockMove ; MOVE.L (SP)+,D0 ; restore the size Ptr2Exit ADD.L D0,D5 ; update file read pointer ADD.L D0,A1 ; update compated region pointer Ptr3Exit CMP.L A1,D4 ; if A1 > D4 then D4 gets A1 BGE.S @1 ; else just exit MOVE.L A1,D4 ; text is true @1 RTS ; ;_______________________________________________________________________________ ; ; Routine: RLocnNew (utility) ; ; Arguments: A1 (input.l) pointer to the end of compacted region ; A3 (input.l) Handle to start of update buffer ; D7 (input.l) the current file write position ; RLocn(A2) (i/o.l) the new file offset for this rsrc ; ; Unchanged: A0-A7,D0-D7 ; Trashed: none ; ; Called By: CmpFrmDsk, CmpFrmMem ; Calls: none ; ; Function: Updates resource map entry to the new file offset. ;_______________________________________________________________________________ RLocnNew MOVEM.L D0-D1/A0,-(SP) ; save D0-D1/a0 across call <10jul85> BBM MOVEQ #-3,D1 ; get ResChanged mask (-3 = $FD = RCBMask) <30jun85> BBM LEA RAttr(A2),A0 ; address of RAttr and RLocn <10jul85> BBM AND.B (A0),D1 ; save old Attr in D1 MOVE.L A1,D0 ; calc file position for this rsrc SUB.L (A3),D0 ; ... by calc how much stuff still in buff ADD.L D7,D0 ; ... and adding to current write position MOVE.L D0,(A0) ; write out new location MOVE.B D1,(A0) ; restore Attributes MOVEM.L (SP)+,D0-D1/A0 ; restore registers RTS ; and go back to caller ;_______________________________________________________________________________ ; ; Routine: WriteSize, WriteZero (utility) <08jul85> BBM ; ; Arguments: A1 (i/o.l) pointer to the end of compacted region ; D0 (input.l) the size to write into the buffer (WriteZero) ; D5 (i/o.l) the current read pointer ; ; Unchanged: A0,A2-A7,D0-D4,D6-D7 ; Trashed: none ; ; Called By: CmpFrmDsk, CmpFrmMem ; Calls: none ; ; Function: Writes D0 into update buffer. Updates the two pointers A1 & D5. ; The size is maintained across call in D0. ;_______________________________________________________________________________ WriteZero MOVEQ #0,D0 ; write out a zero resource size into buff WriteSize ; MOVE.L D1,-(SP) ; save D1 across call MOVEQ #3,D1 ; write D0 (size) into update buffer @0 ROL.L #8,D0 ; write size into buffer MOVE.B D0,(A1)+ ; ... still writing DBRA D1,@0 ; ... loop back until done ADDQ.L #4,D5 ; update file read pointer MOVE.L (SP)+,D1 ; restore D0-D1 BRA.S Ptr3Exit ; and go back to caller ;_______________________________________________________________________________ ; ; Routine: CmpFrmDsk (utility) ; ; Arguments: A1 (i/o.l) pointer to the end of compacted region ; A2 (input.l) pointer to resource entry ; A3 (input.l) Handle to start of update buffer ; A4 (input.l) current map handle ; D3 (input.l) end of the update buffer ; D4 (i/o.l) pointer in buffer (end of stuff read in) ; D5 (i/o.l) the current file read position ; D6 (input.w) the current file refnum ; D7 (i/o.l) the current file write position ; RLocn(A2) (output.l) the new file offset for this rsrc ; ; Unchanged: A2-A7,D1,D3,D6 ; Trashed: A0,D0,D2 ; ; Called By: UpdateResFile ; Calls: _BlockMove, CmpctRead, PartRead, PartWrite, Ptr1Exit, Ptr2Exit, ; RLocnNew, WriteZero ; ; Function: Compacts resource from disk (because the ResChanged bit not set). ; Just does read and compact of one resource. If cann't read in ; all of resource into update buffer, writes out compacted stuff ; and continues until all is done. Also updates RLocn(A2) as well. ; Also, D4 is limited as a lower bound by A1. ;_______________________________________________________________________________ CmpFrmDsk MOVE.L RLocn(A2),D0 ; point to next resource in file AND.L Lo3Bytes,D0 ; make sure high byte cleared for compare <08jul85> BBM SUB.L D5,D0 ; check to see if this RLocn is resonable BGE.S @4 ; CC=GE offset seems good (past stuff written) BSR PartWrite ; make sure we have some room to work in BSR.S RLocnNew ; update rsrc location in map BRA.S WriteZero ; write out zero for size of rsrc & return <08jul85> BBM ;;;RTS ; we really return though WriteZero @4 ADD.L A1,D0 ; add offset to end of compact region ADDQ.L #4,D0 ; add in the size of the rsrc size <03jul85> BBM CMP.L D0,D4 ; is all of the size in memory??? BGE.S @1 ; if it is all in memory go read in size <10jul85> BBM BSR PartWrite ; else get some room to work with MOVE.L RLocn(A2),D0 ; get current position of this resource AND.L Lo3Bytes,D0 ; get rid of the resource attributes MOVE.L D0,D5 ; set up read pointer for next read BSR.S PartRead ; and read in the size @1 MOVE.L RLocn(A2),D0 ; point A0 to Size of resouce BSR.S RLocnNew ; update new position in the map <02jul85> BBM SUB.L D5,D0 ; ... D0 now has delta from D5 to size AND.L Lo3Bytes,D0 ; ... make sure no garbage in high byte MOVE.L A1,A0 ; ... get pointer into buffer ADD.L D0,A0 ; ... A0 now points to the size in memory BSR OddSize ; D0 gets Size of Rsrc; A0 points to Rsrc ADDQ.L #4,D0 ; Also include the size of the resource <13may86> BBM SUBQ.L #4,A0 ; and point A0 to the size of the resource <13may86> BBM MOVE.L D0,D2 ; save size for later ADD.L A0,D2 ; Check to see if all of rsrc is in buffer CMP.L D2,D4 ; is all of rsrc in buffer? BGE Ptr1Exit ; if all in buffer exit by compacting ADD.L A0,D5 ; bump D5 pointer by A0-A1 to É SUB.L A1,D5 ; É keep D5 correct for large files AND.L Lo3Bytes,D5 ; É and make sure no garbage in high byte MOVE.L D0,D2 ; D2 will be count of stuff left to read in <01jan86> BBM MOVE.L D4,D0 ; get the end of the stuff read in SUB.L A0,D0 ; calc the amount of rsrc in update buffer BSR Ptr1Exit ; move it down to compacted space MOVE.L A1,D4 ; since there is no more valid data in buff <10jul85> BBM @2 BSR.S PartWrite ; write out what we have BSR.S PartRead ; Read in more of the resource BEQ.S @9 ; abort if zero bytes read in <17oct85> BBM SUB.L D0,D2 ; update amount of this resource to read MOVE.L A1,A0 ; calc how much of rsrc we just loaded ADD.L D2,A0 ; ... A0 now points to end of rsrc CMP.L A0,D4 ; does rest of rsrc lie in buffer? BGE.S @3 ; ... CC=GE means the rest is in mem MOVE.L D4,D0 ; compact and write what we have SUB.L A1,D0 ; ... by calc how much we have BSR Ptr2Exit ; ... updateing pointers and ... BRA.S @2 ; ... looping back @3 MOVE.L A0,D0 ; calc size of the rest of this rsrc SUB.L A1,D0 ; ... D0 now is size BRA Ptr2Exit ; and exit!!!! @9 MOVE.W #mapReadErr,ResErr ; mark as error for exit <21oct85> BBM BRA Ptr3Exit ; and exit back to update <21oct85> BBM ;_______________________________________________________________________________ ; ; Routine: PartRead (utility) ; ; Arguments: A1 (input.l) pointer to the end of compacted region ; A3 (input.l) Handle to start of update buffer ; A4 (input.l) current map handle ; D3 (input.l) end of input buffer ; D4 (output.l) pointer in buffer (end of stuff read in) ; D5 (input.l) the current file read position ; D6 (input.w) the current file refnum ; ; Unchanged: A0-A7,D0-D3,D5-D7 ; Trashed: none ; ; Called By: CmpFrmDsk ; Calls: RdData ; ; Function: Reads in as much as it can from the file into the update buffer. ; Note that if you haven't used all you read in before, this will ; read in the unused stuff again. Make sure you compact as much ; as possible and call PartWrite before you call this routine. ;_______________________________________________________________________________ PartRead MOVEM.L D0-D2/A0,-(SP) ; save these across call BSR MaxRFEOF ; get EOF in D0 <12sep85> BBM MOVE.L (A4),A0 ; dereference map handle SUB.L D5,D0 ; D0 = amount left to read in. SUB.L ResDataOffset(A0),D0 ; take out bias for D5 AND.L Lo3Bytes,D0 ; make sure no garbage in top byte MOVE.L D3,D1 ; get end of buffer <12sep85> BBM SUB.L A1,D1 ; D1 = amount left in buffer CMP.L D1,D0 ; get minimum of D0/D1 BLE.S @0 ; CC=LE means D0 is already minimum MOVE.L D1,D0 ; else D1 is minimum @0 MOVE.L A1,D1 ; set up destination address MOVE.L D5,D2 ; set up file position ADD.L ResDataOffset(A0),D2 ; take out bias for D5 MOVE.L A1,D4 ; set up new end of read region ADD.L D0,D4 ; update read buffer pointer ; this should never be needed for 24 bit and 32 bit addressing ; AND.L Lo3Bytes,D4 ; make sure high byte cleared BSR RdData ; read data into update buffer (D0 good across call) TST.L D0 ; check if zero byte read call issued <17oct85> BBM MOVEM.L (SP)+,D0-D2/A0 ; restore working registers RTS ; ;_______________________________________________________________________________ ; ; Routine: PartWrite (utility) ; ; Arguments: A1 (i/o.l) pointer to end of data compacted in buff ; A3 (input.l) Handle to beginning of data buffer ; A4 (input.l) Handle to the resource map ; D4 (i/o.l) pointer to end of data read in ; D6 (input.w) the current file refnum ; D7 (i/o.l) file write position - ResDataOffset ; ; Unchanged: A2-A7,D0-D3,D5-D6 ; Trashed: A0 ; ; Called By: CmpFrmDsk ; Calls: _BlockMove, WrData ; ; Function: Writes what has been compacted in the buffer pointed to by (A3), ; and slides the rest forward updating the correct vars. ;_______________________________________________________________________________ PartWrite MOVEM.L D0-D2,-(SP) ; save working registers MOVE.L A1,D0 ; check if anything is ready to be written <01jul85> BBM SUB.L (A3),D0 ; ... get amount already compacted AND.L Lo3Bytes,D0 ; if zero nothing in buffer BEQ.S @9 ; ... if nothing then just return MOVE.L (A4),A0 ; Dereference map for D7 bias correction MOVE.L D7,D2 ; ... D2 will be actual file position ADD.L ResDataOffset(A0),D2 ; ... now D2 is unbiased file write position ADD.L D2,D0 ; force size to be on a 512 byte boundry AND.W #$FE00,D0 ; ... round down to 512 byte boundry SUB.L D2,D0 ; restore D0 to be size to write out BLE.S @9 ; not enough to write out <01jul85> BBM MOVE.L (A3),D1 ; Set up Buff address for write BSR WrData ; do write (NOTE D0 saved across call) ADD.L D0,D7 ; update file write pointer SUB.L D0,A1 ; update end of compact region in buffer SUB.L D0,D4 ; update end of valid data read in MOVE.L A1,-(SP) ; save A0/A1 across blockmove call MOVE.L (A3),A1 ; set up destination for blockmove MOVE.L (A3),A0 ; set up source for blockmove ADD.L D0,A0 ; ... add in offset to source ADD.L D4,D0 ; set up block count for blockmove SUB.L A0,D0 ; ... subtract end pointer AND.L Lo3Bytes,D0 ; ... make sure A0 didn't have garbage <01jul85> BBM _BlockMove ; MOVE.L (SP)+,A1 ; restore A1 to be compact pointer @9 MOVEM.L (SP)+,D0-D2 ; restore working registers RTS ; ;_______________________________________________________________________________ ; ; Routine: PROCEDURE CloseResFile(refNum: INTEGER); ; ; Arguments: 4(SP) (input.L) File refnum ; ; Called By: A-trap through dispatcher, CloseFiles ; Calls: CloseFiles, StdMapEntry, _UpdateResFile, GetEntries, ; _ReleaseResource, GetMap, SetFileIO, _Close, ; _DisposHandle, StdTwoExit ; ; Function: ; Updates, compacts, and closes the given resource file. ; Writes out the possibly changed map and header. Disposes of all ; resources referred to in the map. Unlinks the map from the ; linked list of resource maps, and disposes of the map handle. ; If the refnum given is 0, closes ALL resource files. ;_______________________________________________________________________________ CloseResFile MOVE.L MinusOne,LastSPExtra ; invalidate font cache for font manager MOVE.W HSCMapRNum,D0 ; if the HandleScan cache map refnum... <06may85> BBM CMP.W 4(SP),D0 ; ... equals this maps refnum then ... BNE.S @1 ; ... blitz the cache else skip next ins. CLR.L HSCHandle ; Invalidate cache <12mar85> BBM @1 TST.W 4(SP) ; is it the system resource file? BNE.S ClsRFile ; if not, go on, else BSR CloseFiles ; Close all files other than system ClsRFile BSR StdMapEntry ; Link A6, save regs, get map, exit if none ; Check preventFileFromBeingClosedBit in the resource map. If ; this bit is set, donÕt allow this file to be closed. move.l (a4),a1 ; Pointer to resource map btst #preventFileFromBeingClosedBit,mInMemoryAttr(a1) ; Can this file be closed? bnz @leaveWithoutClosing ; No. DonÕt close it. @doClose BSR CheckAndFlushFontCache ; If we are closing a file w/ fonts we should invalidate the cache @temp ; Attempt an update, writing out all resources with the ResChanged bit set, ; updating the map, and compacting the resource file. MOVE.W D6, -(SP) ; Push the refnum _UpdateResFile ; Update the file. ; Release all the resources ; This section used to call DisposeResource which checked three things: <03mar85> BBM ; handle nil, system reference, and resource marked to be updated. Since ; UpdateResFile was just called there is no point in checking changed bit ; This loop already checks handle nil and system reference, so why not ; call DisposHandle directly. In fact, why not save more time by getting ; trap address and avoiding the dispatcher. (comment part of <3mar85> BBM) MOVE.L #$23,D0 ; calling dispose handle a lot so ... <03mar85> BBM _GetTrapAddress ; ... for speed bypass dispatcher. BSR GetRsrcCnt ; Get to the entries list. <12aug85> BBM BMI.S @3 ; if no entries, don't release resources <28Jan85> BBM MOVE.L A0,A4 ; (A4) = _DisposeHandle. Restored in GetMap <06may85> BBM ADDQ #RHndl,A2 ; Bias A2 in the loop (for speed) <12aug85> BBM @1 MOVE.L (A2)+,D0 ; Get the handle <12aug85> BBM BEQ.S @2 ; if nil, don't attempt a release, else MOVE.L D0,A0 ; get the handle <03mar85> BBM JSR (A4) ; and release it. (_DisposHandle) <06may85> BBM @2 ADDQ.W #RESize-4,A2 ; point at the next entry <12aug85> BBM DBRA D4,@1 ; if more exist, loop back <12aug85> BBM ; Unlink the map from the map list. <28Jan85> BBM @3 BSR GetMap ; Get this map, and previous in D0 <12aug85> BBM MOVE.L MNext(A3), A0 ; Get my next link TST.L D0 ; Did I have a previous map? (i.e. <>top?) BNE.S @4 ; If so, leave topMapHndl the same MOVE.L A0, TopMapHndl ; Otherwise save my next as top map BRA.S @5 ; ...and handle refnum stuff. @4 MOVE.L D0, A1 ; Get previous map in AReg MOVE.L (A1), A1 ; Dereference MOVE.L A0, MNext(A1) ; set previous next as my next @5 CMP.L SysMapHndl, A4 ; Am I removing the system map? BNE.S @6 ; If not, handle normally. LEA TopMapHndl,A0 ; initialize world as in powerup <22jul85> BBM MOVE.L ROMMapHndl,(A0)+ ; make rom map top map <22jul85> BBM MOVE.L ROMMapHndl,(A0)+ ; make rom map system map <22jul85> BBM MOVE.L OneOne,(A0)+ ; set SysMap & curMap to Rom Map RefNum <22jul85> BBM MOVE.L ROMMapHndl,A0 ; zero next map link <22jul85> BBM MOVE.L (A0),A0 ; ... dereference rom map handle <22jul85> BBM CLR.L MNext(A0) ; ... Zero nextMap handle <22jul85> BBM BRA.S @9 ; and close. @6 CMP.W CurMap, D6 ; Am I the current map? BNE.S @9 ; No, everything's ok. If I actually am, MOVE.L (A0), A0 ; Dereference my next (which exists) MOVE.W MRefNum(A0), CurMap ; and save its refnum in CurMap. @9 BSR SetFileIO ; Set up a file block _Close ; And close it. BEQ.S @7 ; if no error use ResErr from UpdateResFile <16apr85> BBM MOVE.W D0, ResErr ; ... else store this code into ResError <16apr85> BBM @7 MOVE.L A4, A0 ; get handle into A0 for dispose _DisposHandle ; Kill map even if error (not recoverable) bra.s @8 @leaveWithoutClosing clr.w ResErr @8 BRA StdTwoExit ; and exit. ;_______________________________________________________________________________ ; ; Routine: FUNCTION CountResources(theType: ResType): INTEGER; ; ; Arguments: 8(A6) (input.L) resource type ; 12(A6) (output.W) number of resources with that type ; ; Called By: A-trap through dispatcher ; Calls: StdEntry, GetTopMap, TypeScan, NextMap, StdFourExit ; ; Function: Given the type, return the number of resources of that type ; accessable in ALL open maps. ;_______________________________________________________________________________ Count1Resources ST ResOneDeep ; entry for one map deep call <22apr85> BBM CountResources BSR StdEntry ; Link A6, save regs CLR.W 12(a6) ; None of this type found so far move.l (a0),-(sp) ; Pust the typeÉ bsr CacheResource ; Build the resource cache for that type move.l ExpandMem,a0 move.l ExpandMemRec.emResourceCache(a0),d0 beq.s @exitCountResourcesOverride move.l d0,a0 move.l (a0),a0 move.l kResourceCount(a0),d1 ; Get count MOVE.W D1,12(A6) ; Save Result @exitCountResourcesOverride BRA StdFourExit ; else, lets exit. ;_______________________________________________________________________________ ; ; Routine: FUNCTION GetIndResource(theType:ResType; index:INTEGER): Handle; ; ; Arguments: 10(A6) (input.L) resource type ; 8(A6),A0(input.W) index ; 14(A6) (output.L) resource handle ; ; Called By: A-trap through dispatcher ; Calls: CheckLoad, GetTopMap, NextMap, SaveCache, SkipToEntry, ; StdEndtry, StdSixExit, TypeScan ; ; Function: Given the type and the index, return the resource handle. ;_______________________________________________________________________________ Get1IndResource ST ResOneDeep ; entry for one map deep call <22apr85> BBM GetIndResource BSR StdEntry ; Link A6, save regs MOVE.W (A0)+, D7 ; Get index in D7 MOVE.L (A0)+, D3 ; and type into D3. CLR.L (A0)+ ; Assume not found. TST.W D7 ; the index<=0 and return not found) stb BLE get1IndErrExit ; stb move.l D3,-(sp) ; Get the resource type we want bsr CacheResource ; Build the resource cache move.l ExpandMem,a0 move.l ExpandMemRec.emResourceCache(a0),d0 ; Get the cache handle beq get1IndErrExit ; If no handle, get out move.l d0,a0 move.l (a0),a0 ; Pointer to cache moveq #0,d0 move.w d7,d0 ; Get index into cache subq #1,d0 ; Cache is zero based cmp.l kResourceCount(a0),d0 ; Check the bounds of the index bge.s get1IndErrExit @validIndex asl.w #3,d0 ; <31> Multiply by 8 to get offset into cache lea kCacheHeaderSize(a0,d0.w),a0 ; Point to proper entry for this index move.l (a0)+,a4 ; <31> Get the map handle (loaded into A4 for CheckLoad) moveq #0,d4 ; <31> move.w (a0),d4 ; <31> Get offset to resource reference list move.l (a4),a3 ; Dereference map handle move.w mRefNum(a3),d6 ; <31> CheckLoad in ROM needs the reference number in D6. moveq #0,d0 ; <37> move.w mTypes(a3),d0 ; <37> Get offset to type list add.w d0,d4 ; <37> Calculate offset of resource reference from beginning of type list move.l d0,HSCTOffset ; <37> Save offset to type list in the cache move.l d4,HSCROffset ; <37> Save offset to resource reference in RMgrHiVars move.l a3,a2 ; Save A3 for CheckLoad add.l d4,a2 ; Point to the resource reference move.l D3,HSCRType ; <37> Save the resource type in the HandleScan cache move.l a4,HSCMapHndl ; <37> Save the map handle in RMgrHiVars move.w d6,HSCMapRNum ; <37> Save map reference number in cache ; Got the correct reference list. Now see if the resource needs to be loaded. Call CheckLoad ; to do this. This requires some setup, since the Resource Manager expects certain ; things from itself. (Since this routine never calls the Resource Manager to set anything ; up, it needs to be done now.) A3 contains a pointer to the type list, and another stack ; frame is created in order to make a parameter block in the place RdData expects it. D6 ; needs to hold the file reference number of the current map. ; ; <11> The decompressor patch calls _Get1Resource from within CheckLoad to load ; the decompressor. At this point, the resource chain is still set up to ; do override stuff. To keep the decompressor working, restore the resource ; chain at this point for _Get1IxResource calls. ; @notOneDeep WITH ResourceMgrStack clr.w ioBlock+ioVRefNum(a6) ; so that it has a IOPB where it clr.w ioBlock+ioFileType(a6) ; expects it on the stack move.b RMgrPerm,ioBlock+ioPermssn(a6) jsr CheckLoad ; Go load the resource if necessary move.l a0,14(a6) ; Return the handle move.l a0,HSCHandle ; <37> And save it in the cache bra.s get1IndOut ENDWITH get1IndErrExit MOVE.W #ResNotFound,ResErr ; ... else mark as an error. get1IndOut BRA StdSixExit ; pop 6 bytes and exit ;_______________________________________________________________________________ ; ; Routine: FUNCTION CountTypes: INTEGER; ; ; Arguments: 8(A6) (output.W) number of types ; ; Called By: A-trap through dispatcher ; Calls: StdEntry, CountITypes, StdZeroExit ; ; Function: Return the number of types in open resource files. ;_______________________________________________________________________________ Count1Types ST ResOneDeep ; entry for one map deep call <22apr85> BBM CountTypes BSR StdEntry ; Link A6, save regs BSR.S CountITypes ; Stack up unique types, D7=count UNLK A6 ; Pop off the types MOVE.W D7, 8(A6) ; Set function result BRA StdZeroExit ; Unlink A6, restore regs ;_______________________________________________________________________________ ; ; Routine: CountITypes (utility) ; ; Arguments: D7.W (output.W) number of unique types ; ; Called By: CountTypes, GetIndType, Count1Types, Get1IndType ; Calls: GetTopMap, GetTypes, NextMap, ChkTypeIgnored ; ; Function: Return a list of unique types on the stack, and D7 = the count. ;_______________________________________________________________________________ CountITypes MOVE.L (SP)+, A0 ; Get return address in A0 LINK A6, #0 ; Link A6 for quick unlk of types MOVEQ #0, D7 ; No types yet BSR GetTopMap ; Get the top map @0 BSR GetTypes ; Get the type list BMI.S @5 ; If no types, go to next map @1 MOVE.L TType(A2), D3 ; Get candidate type in D3 MOVE.L SP, A1 ; Set up climber register MOVE D7, D0 ; Get current count SUBQ #1, D0 ; Zero based for DBRA BMI.S @3 ; if none yet, just add @2 CMP.L (A1)+, D3 ; is this type already represented? DBEQ D0,@2 ; loop back for count of types <01may85> BBM BEQ.S @4 ; If so, go to next type in map @3 MOVE.L D3, -(SP) ; Push the new type on the stack ADDQ #1, D7 ; Increment type count @4 ADDQ.L #TSize, A2 ; Skip to next type entry DBRA D5, @1 ; and loop back. @5 BSR NextMap ; Link to next map BEQ.S @0 ; If there are more, loop back. FPCallCountIExit ; FlashPort hint attachment point JMP (A0) ; and return. D7=one's based count, ; stack has the types. ;_______________________________________________________________________________ ; ; Routine: PROCEDURE GetIndType(VAR theType: ResType; index: INTEGER); ; ; Arguments: 10(A6) (input.L) resource type ; 8(A6),A0(input.W) resource ID ; 14(A6) (output.L) resource handle ; ; Called By: A-trap through dispatcher ; Calls: StdEntry, CountITypes, StdSixExit ; ; Function: Given the index, return indexed type in the current resource map. ;_______________________________________________________________________________ Get1IndType ST ResOneDeep ; entry for one map deep call <22apr85> BBM GetIndType BSR StdEntry ; Link A6, save regs MOVE.W (A0)+, D2 ; Get index number in D2, MOVE.L (A0), D1 ; and VAR address in D1. BSR.S CountITypes ; Make type list on stack MOVE.L D1, A0 ; Get VAR address in AReg CLR.L (A0) ; Assume failure SUBQ.W #1, D2 ; Make count zero based BMI.S @9 ; if count was <=0, exit with error. CMP.W D2, D7 ; is it > max? BLE.S @9 ; if so, use error result. ASL.W #2, D2 ; (count-1)*4 for offset MOVE.L 0(SP, D2), (A0) ; Set function result @9 UNLK A6 ; Pop off the types (linked in CountITypes) BRA StdSixExit ; and exit ;_______________________________________________________________________________ ; ; Routine: FUNCTION UniqueID(theType: ResType): INTEGER; ; ; Arguments: 8(A6) (input.L) resource type ; 12(A6) (output.W) Unique ID ; ; Called By: A-trap through dispatcher ; Calls: StdEntry, GetTopMap, _Random, TypeScan, SkipToEntry, IDScan, ; IDScanAll, NextMap, StdFourExit ; ; Function: Return a unique ID for a given type. The ID is unique across ; ALL maps that are currently open. The ID is always > 127. <13> stb ;_______________________________________________________________________________ Unique1ID ST ResOneDeep ; entry for one map deep call <22apr85> BBM UniqueID BSR StdEntry ; Link A6, save regs MOVE.W Ticks+2, D7 ; Get low ticks for initial ID guess @0 BSR GetTopMap ; Get the top map SUBQ #2, SP ; Make room for result _Random ; Get Bill's random number ADD.W (SP)+, D7 ; Increment ticks by a random amount. AND.W #$7FFF, D7 ; Force it positive for no good reason MOVE.L 8(A6), D3 ; Get type in D3 MOVE.W D7, D2 ; Copy ID candidate to D2. CMP.W #128, D2 ; is it legal? <13> stb CSS BLT.S @0 ; if not, try again <13> stb @1 BSR TypeScan ; Try to find the type. BMI.S @2 ; if MI, no such type BSR SkipToEntry ; Skip to the first entry of that type BSR IDScan ; Now try to find the ID BEQ.S @0 ; if found, need a new random ID. @2 BSR NextMap ; follow link to next map BEQ.S @1 ; If there is another map, scan it, MOVE.W D2, 12(A6) ; else, Return the unique ID BRA StdFourExit ; and exit. ;_______________________________________________________________________________ ; ; Routine: FUNCTION GetResource(theType: ResType; theID: INTEGER): Handle; ; ; Arguments: 10(A6) (input.L) resource type ; 8(A6),A0(input.W) resource ID ; 14(A6) (output.L) resource handle ; ; Called By: A-trap through dispatcher ; Calls: StdEntry, GetCurMap, TypeScan, SkipToEntry, IDScan, NextMap, ; CheckLoad, StdSixExit, GetTopMap, SaveCache ; ; Function: Given a type and ID, return the handle to the resource. Searches ; all maps starting with the current map and ending with the system ; map. ; NOTE: ; May not search all open maps, depending which the current map is. ;_______________________________________________________________________________ Get1Resource returnAddress EQU 0 theResID EQU returnAddress+4 theResType EQU theResID+2 ST ResOneDeep ; entry for one map deep call <22apr85> BBM IF hasRISCV0ResMgrPatches THEN BRA realGetRes GetResource ; BT ; first do GetResource ProcessManager patch if the process manager is around MOVE.L ExpandMem,A0 ; get ExpandMem TST.W ExpandMemRec.emProcessMgrExists(A0) ; is the process manager here? BEQ.S realGetRes ; nope, blow the patch ; the patch checks to see if we have old PrintMgr.o glue trying to print ; by loading the resource and calling it directly. If so, we need to deal ; with the local/global printer scheme for the glue, since _PROpenDriver isn't ; going to be there to cover for us moveq.l #0,d0 move.l 6(sp),a0 ; get res type cmp.l #'PDEF',a0 ; is this a potential print entry point? bne.s realGetRes ; if not, branch move.w 4(sp),d0 ; get res id (whole word) cmp.w #7+1,d0 ; is it 0-7? bcc.s realGetRes ; if not, branch to real call movem.l d1-d2/a1,-(sp) ; save work regs lea -10(sp),sp ; room for 2 pointers + return value (on bottom) pea 6(sp) ; push ptr to one ptr pea 6(sp) ; push ptr to the other ptr _MFGetPrTypeStrings ; get local and global ref nums moveq.l #0,d0 ; assume pr types the same tst.b (sp)+ ; is pr type locked for this guy? beq.s @sameString ; if so, branch (treat as strings equal) move.l 0(sp),a0 ; get first string in a0 move.l 4(sp),a1 ; get second string in a1 moveq.l #0,d0 ; clear out d0 move.b (a0)+,d0 ; d0.w <- length of first string swap d0 move.b (a1)+,d0 ; d0.w <- length of second string _RelString ; call it move.l 4(sp),d2 ; save local name ; get here with condition codes saying whether the types are the same @sameString addq.w #8,sp ; get rid of the 2 string ptrs tst.w d0 ; are they the same? beq.s @GotoPDEF ; if equal, branch ; Set the printer type for the current process, give a _Close call to the .Print driver, and ; then give it an _Open call. If the driver is not in yet, _Close will return an error which ; we ignore. If it is in, it simple passes it along to the appropriate .XPrint. subq.w #2,sp ; room for return result move.l d2,-(sp) ; push local name move.w BootDrive,-(sp) ; has to be in sys folder move.b #fsCurPerm,-(sp) ; default arg (need to r/w probably) _OpenRFPerm ; bring to front (already opened) move.w (sp)+,d2 ; save the refnum _PrDrvrOpen ; Open new driver, thus closing old one move.w d2,-(sp) ; push refnum of (old) local pr type name _CloseResFile ; close old driver's res file move.l TopMapHndl,a0 ; get top map move.l (a0),a0 ; hdl -> ptr move.l MRefNum(a0),CurMap ; force new guy (who is at top) to be current @GotoPDEF movem.l (sp)+,d1-d2/a1 ; restore work regs ; BT end of patch, do the real thing ELSE GetResource ENDIF realGetRes BSR StdEntry ; Link A6, save regs BSR GetCurMap ; Get handle to current map BPL.S @2 ; fix an old finder bug with new roms <25mar85> BBM BSR GetTopMap ; ... when get resource passed bad RefNum @2 MOVE.W (A0)+, D2 ; Get resource ID in D2 MOVE.L (A0)+, D3 ; and type in D3 CLR.L (A0) ; Assume not found @0 BSR TypeScan ; Try to find the type BMI.S @1 ; if MI, no such type, get next map BSR SkipToEntry ; Skip to the first entry of that type BSR IDScan ; Now try to find the ID BEQ.S @8 ; If EQ, found it! Otherwise try next map @1 BSR NextMap ; follow link to new map BEQ.S @0 ; If there is another map, try again, ;<17jun85> BBM MOVE.W #ResNotFound,ResErr ; ...else mark as error <16apr85> BBM BRA.S @9 ; else not found. @8 BSR SaveCache ; valid most of cache for handle scan <30apr85> BBM BSR CheckLoad ; Check handle, init/load it if needed MOVE.L A0, 14(A6) ; Save result--fall through to exit. MOVE.L A0,HSCHandle ; finish validating cache <30apr85> BBM @9 BRA StdSixExit ; else not found. ;_______________________________________________________________________________ ; ; Routine: FUNCTION GetNamedResource(theType:ResType;theName:Str255):Handle; ; ; Arguments: 12(A6) (input.L) resource type ; 8(A6) (input.L) pointer to resource name ; 16(A6) (output.L) resource handle ; ; Called By: A-trap through dispatcher ; Calls: StdEntry, GetCurMap, TypeScan, SkipToEntry, NamedResource, ; _CmpString, NextEntry, NextMap, CheckLoad, StdExit, SaveCache ; ; Function: Given a type and name, return the handle to the resource. ; Searches all maps starting with the current map and ending with ; the system map. ; NOTE: ; May not search all open maps, depending which the current map is. ;_______________________________________________________________________________ Get1NamedResource ST ResOneDeep ; entry for one map deep call <22apr85> BBM GetNamedResource BSR StdEntry ; Link A6, save regs BSR GetCurMap ; Get the current map MOVE.L (A0), A1 ; Get name pointer in A1. CLR.L 16(A6) ; Assume the resource was not found @1 MOVE.L 12(A6), D3 ; Get type of resource in D3 for scan. BSR TypeScan ; Look for the type BMI.S @4 ; If no such type found, get next map BSR SkipToEntry ; Walk through the entries of this type. @2 BSR NameResource ; Given RNameOff(A2), return name in A0. BMI.S @3 ; if CC=MI, didn't find name (A1=target string) MOVEQ #0, D0 ; Clear out high bits MOVE.B (A0)+, D0 ; Get length (trash A0!) SWAP D0 ; and put it in high order MOVE.B (A1)+, D0 ; Get length of second string in low order _CmpString ; Check equality of strings in A0 and A1 SUBQ #1, A1 ; Point back to the Pascal string in A1 BEQ.S @8 ; If equal, load it in! @3 BSR NextEntry ; Skip to next entry BEQ.S @2 ; If not changed type, get next res @4 BSR NextMap ; Link to next map BEQ.S @1 ; if one exists, go search it, MOVE.W #ResNotFound,ResErr ; ...else mark as error <16apr85> BBM BRA.S @9 ; ...and exit. @8 BSR SaveCache ; valid most of cache for handle scan <30apr85> BBM BSR CheckLoad ; otherwise load it in, if necessary. MOVE.L A0,16(A6) ; Save the handle as function result MOVE.L A0,HSCHandle ; finish validating cache <30apr85> BBM @9 MOVEQ #8, D0 ; pop off eight bytes of parameter BRA StdExit ; and exit. ;=== RmgrAsm2.a Starts Here ============================================================= ;_______________________________________________________________________________ ; ; The following routines are all of the same form: GET*. ; Given a parameter, point registers to *. ;_______________________________________________________________________________ ;_______________________________________________________________________________ ; ; Routine: GetTopMap (utility) ; ; Arguments:: A4 (input.L) handle top map ; A2 (output.L) pointer top map ; A3 (output.L) pointer top map (same as A2) ; A4 (output.L) handle top map ; D0 (output.L) handle previous map (if BNE GetCurMap) ; D6 (output.W) top map refnum ; ; Called By: CountResources, GetIndResource, CountITypes, UniqueID, ; GetResource, HandleScan ; Calls: GetCurMap ; ; Function: Set up regs for the current topmost resource map. ;_______________________________________________________________________________ GetTopMap BLANKS ON STRING ASIS TST.B ResOneDeep ; if one is set get current map instead <26jun85> BBM BNE.S GetCurMap ; ... else fall through to GetTopMap. MOVE.L TopMapHndl, A4 ; Get topMap handle MOVE.L (A4), A3 ; Dereference it MOVE.W MRefNum(A3), D6 ; Get reference number MOVE.L A3, A2 ; Copy it in A2 RTS ; Block handle in A4, ptr in A3 and A2 ;_______________________________________________________________________________ ; ; Routine: GetCurMap, GetMap (utilities) ; ; Arguments: D6 (input.W) map refnum ; A4 (output.L) handle to new map ; A3 (output.L) pointer to new map ; A2 (output.L) pointer to new map ; D0 (output.L) handle of previous map ; ; Called By: (GetCurMap): PreLoad, PreLoad2, RsrcZoneInit, GetResource, ; GetNamedResource, AddResource ; (GetMap): SetResFileAttrs, StdMapEntry, CloseResFile ; Calls: NONE ; ; Function: Set up registers for resource map specified by refnum in D6. ; GetCurMap sets D6 to the current map refnum & calls get map. ; D0 = 0 if no previous Map. ;_______________________________________________________________________________ GetCurMap MOVE.W CurMap, D6 ; Get current resFile refnum. GetMap TST.W D6 ; Test refnum (system special, or none) BMI NotFound ; if -ve, no maps open--exit with error. BNE.S @1 ; If not zero, use standard resource MOVE.W ResourceMgrStack.OverrideSysMap(a6),D6 ; Otherwise use refnum of system map @1 MOVE.L TopMapHndl, A4 ; Get top map handle MOVEQ #0, D0 ; Initialize prev map handle BRA.S @3 ; Get next map (jump into loop) @2 MOVE.L MNext(A3),D0 ; Get handle to the next map. BEQ NotFound ; If the handle was nil, not found EXG A4,D0 ; set A4, and last map handle in D0. @3 MOVE.L (A4),A3 ; Dereference CMP.W MRefNum(A3),D6 ; Is it the right resource map? BNE.S @2 ; no, skip to the next one MOVE.L A3, A2 ; Copy it in A2 RTS ; Block handle in A4, ptr in A3 and A2 ;_______________________________________________________________________________ ; ; Routine: NextMap (utility) ; ; Arguments: A4 (input.L) resource map handle ; A3 (output.L) pointer to next map ; A4 (output.L) handle to next map ; D6 (output.L) refnum to next map ; ; Called By: HandleScan, CountIResources, CountITypes, UniqueID, GetResource, ; GetNamedResource ; Calls: NONE ; ; Function: Given map handle in A4 Set up map handle, pointer, refnum of ; next map. Returns EQ if found, MI if not ;_______________________________________________________________________________ NextMap move.l a0,-(sp) ; save off a0 TST.B ResOneDeep ; if one deep set, don't get next map <26jun85> BBM BEQ.S @1 ; ... else do normal stuff move.l ExpandMem,a0 ; <41> tst.b ExpandMemRec.emScanOverrideMaps(a0) ; <41> Is overriding on? beq.s @3 ; <41> No. don't check the 2 deep bit. ; The requested resource wasnÕt found in the map in A4. Check if the twoDeepBit is set on this ; map, and if it is, search the next map down. move.l (a4),a3 ; Try the next map, but only if this map has twoDeep set. btst #twoDeepBit,mInMemoryAttr(a3) ; Is the twoDeepBit set? BNE.S @1 ; ... yes ignore oneDeep, so don't zero handle @3 SUBA.L A4,A4 ; Zero Handle and error exit. BRA.S @2 ; ... and return <19jun85> BBM @1 MOVE.L (A4), A3 ; Dereference map handle MOVE.L MNext(A3), A4 ; Get next handle @2 move.l (sp)+,a0 ; restore a0 MOVE.L A4, D0 ; Was the handle zero? BEQ NotFound ; If no more maps MOVE.L (A4), A3 ; Otherwise dereference MOVE.W MRefNum(A3), D6 ; Get new refnum also BRA Found ; Say it was found ;_______________________________________________________________________________ ; ; Routine: GetTypes (utility) ; ; Arguments: A4 (input.L) map handle ; A2 (output.L) pointer to first type ; A3 (output.L) pointer to type block in map ; D5 (output.W) Type count ; ; Unchanged: A0-A1,A4-A7,D0-D4,D6-D7 ; Trashed: NONE ; ; Called By: AddNewRef, CountITypes, GetEntries, TypeScan ; Calls: NONE ; ; Function: Given map handle in A4, Returns A2 pointing to the first type. ; A3 points to type block. D5 is type count. ;_______________________________________________________________________________ GetTypes MOVE.L (A4), A3 ; Dereference map handle ADDA.W MTypes(A3), A3 ; Add offset to type list MOVE.L A3, A2 ; Copy top of block MOVE.W (A2)+, D5 ; Get type count, point to first type RTS ;_______________________________________________________________________________ ; ; Routine: GetRsrcCnt (utility) <10may85> BBM ; ; Arguments: A4 (input.L) map handle ; A2 (output.L) pointer to first rsrc entry ; A3 (output.L) trashed ; D3 (output.W) the first type ; D4 (output.W) number of rsrc entries in map (minus one) ; D5 (output.W) D5 = $FFFF (always) ; ; Unchanged: A0-A1,A4-A7,D0-D2,D6-D7 ; Trashed: A3,D3,D5 ; ; Called By: Preload/Preload2, RomMapEntry, ReDoMap ; Calls: GetEntries ; ; Function: Set up D4 for looping through resource entries in map. If you ; need to go through every rsrc in the map call this routine, and ; do the following loop: ; ; @1 ...Code ; put your code here ; ADD.W #RESize,A2 ; point to next entry ; DBRA D4,@1 ; loop back if more entries ; ;_______________________________________________________________________________ GetRsrcCnt BSR.S GetEntries ; set up regs for the count BMI.S @9 ; if no entries just return with CC=MI ADDQ #TCount+2,A3 ; point to 1st count (+2 is for TypeCount) ADD.W D5,D4 ; D4 already has first count (Getentries) BRA.S @1 ; jump into loop check @0 ADDQ #TSize,A3 ; skip to count in the next type ADD.W (A3),D4 ; Add this count into D4 @1 DBRA D5,@0 ; if more types loop back @9 RTS ; else return with CC= error state ;_______________________________________________________________________________ ; ; Routine: GetEntries (utility) ; ; Arguments: A4 (input.L) map handle ; A2 (output.L) pointer to the first ID ; A3 (output.L) points to type block ; D3 (output.W) the first type ; D4 (output.W) entry count (of the first type) ; D5 (output.W) type count ; ; Unchanged: A0-A1,A4-A7,D0-D2,D6-D7 ; Trashed: none ; ; Called By: HandleScan, RsrcZoneInit, CloseResFile, RmveName ; Calls: GetTypes, SkipToEntry ; ; Function: set up regs from map handle for entry munging. ;_______________________________________________________________________________ GetEntries BSR.S GetTypes ; A2 points to first type, D5 is NTypes MOVE.L TType(A2), D3 ; Set the type BSR.S SkipToEntry ; Skip to the first entry of that type TST.W D5 ; Set CC's RTS ; ...and return. ;_______________________________________________________________________________ ; ; The following routines are all of the same form: *Scan. ; Scan for * within the map. If found, return CC=EQ. If not found, return ; CC=MI. A2 points to the correct entry. ;_______________________________________________________________________________ ;_______________________________________________________________________________ ; ; Routine: IDScan (utility) ; ; Arguments: A2 (input.L) pointer to first entry of given type ; D2 (input.W) ID of desired entry ; D4 (input.W) Entry count ; A2 (output.L) pointer to correct entry (if found) ; ; Unchanged: A0-A1,A3-A7,D1-D3,D5-D7 ; Trashed: D0,D4 ; ; Called By: GetResource ; Calls: NotFound, SubA2Found ; ; Function: Searches for desired entry. If found, return CC=EQ, else CC=MI. ;_______________________________________________________________________________ IDScan MOVEQ #RESize,D0 ; Set up D0 with Rsrc Size for loop <01may85> BBM @1 CMP.W RID(A2), D2 ; Is it the right ID? (note: RID=0) ADDA.W D0,A2 ; Skip to next ID, if any DBEQ D4,@1 ; Loop back, unless no more or found ID <01may85> BBM BEQ.S SubA2Found ; if found, exit by adjusting A2 BRA.S NotFound ; If made it to here, not found ;_______________________________________________________________________________ ; ; Routine: TypeScan (utility) ; ; Arguments: A4 (input.L) map handle ; D3 (input.L) resource type ; A2 (output.L) pointer to type entry ; D4 (output.W) entry count ; D5 (output.W) type count remaining ; ; Called By: CountIResources, UniqueID, GetResource, AddNewRef, ; GetNamedResource, RmveCmn ; Calls: GetTypes, ChkTypeIgnored ; ; Function: Set up returned registers from map handle. CC=MI if no types in ; map or entry type not found. ;_______________________________________________________________________________ TypeScan BSR.S GetTypes ; A2 -->first type, D5 is type count BMI.S NotFound ; No types listed! MOVEQ #TSize,D0 ; Delta to next type <01may85> BBM @1 CMP.L TType(A2), D3 ; Is it the right type? (note TType=0) ADDA.W D0,A2 ; Skip to next type DBEQ D5,@1 ; Decrement and try again, unless found <01may85> BBM BEQ.S SubA2Found ; if found, exit by adjusting A2 BRA.S NotFound ; If made it to here, not found ;_______________________________________________________________________________ ; ; Routine: SkipToEntry ; ; Arguments: A2 (input.L) pointer to type entry ; A2 (output.L) ptr to first res of input type (or NIL) ; D4 (output.W) entry count ; D5 (output.W) type count remaining ; ; Called By: GetEntries, CountIResources, UniqueID, GetResource, ; GetNamedResource, AddNewRef ; Calls: NONE ; ; Function: Set up registers from input type entry pointer. Returns pointing ; to the first resource entry of that type, or nil. ; (21may85 - now can handle 64k offsets correctly.) ;_______________________________________________________________________________ SkipToEntry MOVE.W TCount(A2), D4 ; Copy entry count of first type into D4 MOVE.L D0,-(SP) ; make sure to preserve D0 <21may85> BBM MOVEQ #0,D0 ; clear top half of D4 for 64k offset MOVE.W TOffset(A2), D0 ; Copy offset to first entry MOVE.L D0,A2 ; move to address reg. MOVE.L (SP)+,D0 ; make sure to restore D0 <21may85> BBM ADD.L A3, A2 ; Adding in block address gives entry address RTS ; ...and return ;_______________________________________________________________________________ ; ; Routine: Found, NotFound, SubA2Found ; ; Arguments: D0 (output.L) CC=EQ is found, CC=MI is Not found ; ; Called By: (found): nearly everyone ; (SubA2Found): IDScan ; (NotFound): nearly everyone ; Calls: NONE ; ; Function: these routines set up D0 and the condition codes for proper rts. ; SubA2Found also adjusts A2 to point at the 'right' entry. ;_______________________________________________________________________________ SubA2Found SUBA.W D0,A2 ; adjust A2 and fall into found. <01may85> BBM Found MOVEQ #0, D0 ; Set CC=EQ RTS NotFound MOVEQ #-1,D0 ; Set CC=MI RTS ;_______________________________________________________________________________ ; ; Routine: StdZEntry, Std1Entry, StdEntry (utilities) ; ; Arguments: A0 (output.L) ; ; Called By: everyone (well, almost) ; Calls: NONE ; ; Function: Links A6, saves ALL regs except A0 and D0. A0 is returned ; pointing to the last parameter, for (A0)+ traversals. ; ; WARNING: Currently this routine preserves D0. OpenRFPerm depends on D0 ; not changing across the call. DO NOT MODIFY. ; Add Resource also depends on this!! ;_______________________________________________________________________________ StdZEntry CLR.W RomMapInsert ; don't insert ROM Map <09jul85> BBM Std1Entry CLR.B ResOneDeep ; disable one deep stuff <26jun85> BBM StdEntry MOVE.L JRMgrStdEntry,A0 ; get the vector from the OSJumptable <1.2> BBM JMP (A0) ; and go to the routine <1.2> BBM vRMgrStdEntry ; Def to build dispatch entry <1.2> BBM WITH ResourceMgrStack, ExpandMemRec CLR.W ResErr ; Clear the error flag MOVE.L (SP)+, A0 ; Get return address in A0 LINK A6, #localSize ; Link A6 for IOStkFrame stb CLR.W ioBlock+IOVRefNum(A6) ; always default to default volume and ... <05sep85> BBMstb CLR.W ioBlock+IOFileType(A6) ; File type Zero etc. <05sep85> BBMstb CLR.L ioBlock+ioDirID(A6) ; zero out the dir ID CLR.B ioBlock+ioPermssn(A6) ; zero out the permissions byte MOVEM.L A1-A4/D1-D7, -(SP) ; Save registers SUBA.L A4,A4 ; since IO calls sub (A4) make sure even <03jun85> BBM MOVE.L A0, -(SP) ; Push A0 back on as return LEA 8(A6), A0 ; Point A0 at last parameter movem.l a0-a5/d0-d5,-(sp) ; Save work registers for override setup move.w CurMap,realCurMap(a6) ; Save a copy of real CurMap clr.w doOverrides(a6) ; assume no overrides for nowÉ clr.w overrideCurMap(a6) ; assume no overrides for nowÉ ; Save default values for SysMap and SysMapHndl move.l SysMapHndl,OverrideSysMapHndl(a6) ; save the handle move.w SysMap,OverrideSysMap(a6) ; Get reference number for SysMap ; As far as I can tell, CurMap is only negative before InitResources is called. ; If this is the case, we certainly don't want to save and restore curmap ; to a negative oneÉ tst.w CurMap ; Special system case, bailÉ bmi @noOverrideMap ; no overrides ( changed short branch to long ) kc move.l ExpandMem,a0 ; Get the expandmem rec ptr tst.b emScanOverrideMaps(a0) ; Is overriding on? beq.s @noOverrideMap ; No. Use the old resource mgr stuff. move.w #1,doOverrides(a6) ; overrides are on. bsr GetCurMap ; Get the Current Map in A4(Handle) and A3 (Ptr) bmi.s @getSystemMap ; -> failed. Use the system map. move.w emLastMapOverridden(a0),d0 ; Get the last map that was overriden bz.s @GetOverrideMap ; If refnum is 0, then go get the override map. kc cmp.w CurMap,d0 ; If the refnum is the same as last time, kc beq.s @UseCachedMap ; skip all the work kc @GetOverrideMap ; kc ; kc subq #4,sp ; move.l a4,-(sp) ; <23> Find override map for current resource map _GetOverrideMap ; Get an override map for it move.l (sp)+,d0 ; Get override map (it may be the map itself) bz.s @getSystemMap ; Assume no override map if this map wasnÕt found cmp.l a4,d0 ; did we get an override map? beq.s @getSystemMap ; no they're the sameÉ ; WeÕve got an override map for the current resource map. Set the override map to be the ; current map for the duration of this Resource Manager call. move.l d0,a1 move.l (a1),a0 move.w mRefNum(a0),d0 ; Get reference number of override map move.l ExpandMem,a0 ; Cache override and overridden refnums kc move.w CurMap,emLastMapOverridden(a0) ; Remember the last map we overrode. kc move.w d0,emOverrideMapRefNum(a0) ; Remember the override map refnum. kc ; kc @UseCachedMap ; kc move.w emOverrideMapRefNum(a0),d0 ; Get override refnum from the cache kc ; kc move.w d0,CurMap ; Make the Resource Manager start with an override map move.w d0,overrideCurMap(a6) ; store the override map. @getSystemMap move.w SysMap,D6 BSR GetMap ; Get the System Map in A4(Handle) and A3 (Ptr) bmi.s @noOverrideMap ; -> Couldn't find the map. subq #4,sp ; move.l a4,-(sp) ; <23> Find override map for current resource map _GetOverrideMap ; Get an override map for it move.l (sp)+,d0 ; Get override map (it may be the map itself) bz.s @noOverrideMap ; Assume no override map if this map wasnÕt found move.l d0,OverrideSysMapHndl(a6) ; save the handle move.l d0,a1 move.l (a1),a0 move.w mRefNum(a0),OverrideSysMap(a6) ; Get reference number of override map @noOverrideMap TST.B RomMapInsert ; do I need to insert ROM Map <26jun85> BBM BEQ.S @done ; if zero don't add MOVEQ #0,D1 ; tell SwapRomMap to add BSR.S SwapRomMap ; else go add ROM map @done movem.l (sp)+,a0-a5/d0-d5 RTS ; and return. ENDWITH ;_______________________________________________________________________________ ; ; Routine: SwapRomMap (utility) <26jun85> BBM ; ; Arguments: D1 (input.w) 0 means add map; -1 means remove map ; ; Unchanged: A0-A7,D0-D7 ; Trashed: NONE ; ; Called By: StdEntry, StdExit ; Calls: NONE ; ; Function: called by standard entry and exit to either add in the rommap to ; the map chain, or delete the rommap from the map chain. ; ; Now that we have overrides, we want to put the ROM map at the ; very end of the resource chain when swapping it out ; and we want to put it in front of any system override maps ; when swapping inÉ ;_______________________________________________________________________________ SwapRomMap ; MOVEM.L A0-A3/D0-D2,-(SP) ; Save all regs used move.l d1,-(sp) ; save d1 trashed by GetOverrideMap MOVEA.L ResourceMgrStack.OverrideSysMapHndl(a6),A3 ; Hold the override map in a3 the link we're looking for move.l (sp)+,d1 ; restore d1 trashed by GetOverrideMap MOVEA.L ROMMapHndl,A2 ; A2 has the ROM Map CMPA.L A3,A2 ; if A3=A2 then only ROM map around so... BEQ @9 ; ... just return ; ; If we are swapping inÉ ; if CurMap == SysMap then make CurMap= ROMMap (1) ; else if we are swapping outÉ ; if CurMap == ROMMap then make CurMap SysMap ; TST.L D1 ; determine if we are inserting or removing the rommap BNE.S @removing ; -1 means removing ROM Map MOVE.W CurMap,D0 ; for check if curmap needs changing <10jul85> BBM @0 CMP.W ResourceMgrStack.OverrideSysMap(a6),D0 ; if SysMap=CurMap <10jul85> BBM BNE.S @1 ; MOVE.W #1,CurMap ; ... then CurMap gets RomMap ;InsertingÉ Put the rom resource map above the System Override fileÉ @1 MOVEA.L TopMapHndl,A0 ; start at top and find map before A0 @2 MOVE.L (A0),A0 ; dereference it to get pointer MOVE.L MNext(A0),D0 ; get the next map handle into A0 BEQ.S @4 ;;;;;;; error!!! CMP.L A3,D0 ; is this the map we want BEQ.S @3 ; found the right map MOVE.L D0,A0 ; Make A0 a handle to the next map BRA.S @2 ; and loop back for next check @3 MOVE.L A2,MNext(A0) ; put in right link BRA.S @5 ; skip to exit code @4 CMP.L TopMapHndl,A3 ; if (topmaphndl <> A1) then ... BNE.S @5 ; ... don't change topmaphndl MOVE.L A2,TopMapHndl ; topmap is now the right link @5 MOVE.L ROMMapHndl,A0 ; Point ROM to sysmap MOVE.L (A0),A0 ; ... Dereference map handle to pointer MOVE.L A3,MNext(A0) ; ... and point ROM to sysmap (possibly overidden) bra.s @exit @removing MOVE.W CurMap,D0 ; for check if curmap needs changing <10jul85> BBM CMP.W #1,D0 ; is RomMap=CurMap BNE.S @begin ; MOVE.W ResourceMgrStack.OverrideSysMap(a6),CurMap ; ... then make the system the current map ; Find the map that is above the ROM Map so we can point it around the ; ROM Map @begin MOVEA.L TopMapHndl,A0 ; start at top and find map before A0 @loop MOVE.L (A0),A0 ; dereference it to get pointer MOVE.L MNext(A0),D0 ; get the next map handle into A0 BEQ.S @6 ;;;;;;; error!!! CMP.L A2,D0 ; is this the map we want BEQ.S @7 ; found the right map MOVE.L D0,A0 ; Make A0 a handle to the next map BRA.S @loop ; and loop back for next check @6 CMP.L TopMapHndl,A2 ; if (topmaphndl <> Rom Map) then ... BNE.S @7 ; ... don't change topmaphndl MOVE.L A3,TopMapHndl ; topmap is now the system map (or its override) bra.s @exit @7 move.l (A2),A1 ; Ptr to ROM Map is now in A1 move.l MNext(A1),MNext(A0) ; Cut ROM out of the loopÉ MapBeforeROMMap->next = ROMMap->next @exit MOVE.B ResLoad,D0 ; Swap ResLoad and TmpResLoad MOVE.B TmpResLoad,ResLoad ; ... Swap continued MOVE.B D0,TmpResLoad ; ... Swap continued @9 MOVEM.L (SP)+,A0-A3/D0-D2 ; Save all regs used RTS ; ;_______________________________________________________________________________ ; ; Routine: StdExit,StdZeroExit,StdTwoExit,StdFourExit,StdSixExit(utilities) ; ; Arguments: D0 (input.L) # of bytes to pop off stack before exit ; A6 (input.L) LINKed register ; ; Called By: everyone ; Calls: NONE ; ; Function: Unlinks A6, restores ALL regs except A0, D0. Call ResErrHook if ; ResErr<>0. ResErrProc called with error in D0 and return ; address of caller on stack. The hook can therefore filter ; errors and return to caller. ;_______________________________________________________________________________ StdTwelveExit MOVEQ #12,D0 ; standard eight byte exit BRA.S StdExit ; and exit StdTenExit ; MOVEQ #10,D0 ; standard six byte exit BRA.S StdExit ; and exit StdEightExit ; MOVEQ #8,D0 ; standard six byte exit BRA.S StdExit ; and exit StdSixExit ; MOVEQ #6,D0 ; standard six byte exit BRA.S StdExit ; and exit StdFourExit ; MOVEQ #4,D0 ; standard four byte exit BRA.S StdExit ; and exit StdTwoExit ; MOVEQ #2,D0 ; standard two byte exit BRA.S StdExit ; and exit StdZeroExit ; MOVEQ #0,D0 ; standard Zero byte exit RStdExit ; <9> rb StdExit MOVE.L JRMgrStdExit,A1 ; get the vector from the OSJumptable <1.2> BBM JMP (A1) ; and go to the routine <1.2> BBM vRMgrStdExit ; Def to build dispatch entry <1.2> BBM tst.w ResourceMgrStack.doOverrides(a6) beq.s @noOverrides move.w ResourceMgrStack.overrideCurMap(a6),d1 ; did the resource manager change the CurMap? beq.s @noOverrides cmp.w CurMap,d1 bne.s @noOverrides ; yes, so leave it alone move.w ResourceMgrStack.realCurMap(a6),CurMap ; Restore real CurMap @noOverrides TST.B RomMapInsert ; do I need to insert ROM Map <26jun85> BBM BEQ.S @1 ; if zero don't add MOVEQ #-1,D1 ; tell SwapRomMap to Delete ROM map BSR SwapRomMap ; else go add ROM map @1 CLR.B ResOneDeep ; always stop one deep calls <09jul85> BBM CLR.W RomMapInsert ; always disable rom map next time <09jul85> BBM MOVEM.L (SP)+, A1-A4/D1-D7 ; Restore registers UNLK A6 ; Unlink A6 MOVE.L (SP)+, A0 ; Get return address in A0 ADD.L D0, SP ; Pop off parameter MOVE.L A0, -(SP) ; Push return back SUBA.L A0,A0 ; Zero A0 for Duvall's Edit? <19mar85> BBM MOVE.W ResErr, D0 ; Get ResErr in D0 BEQ.S StdExitOut ; If equal, just return, otherwise FPCallResErrProc ; FlashPort hint attachment point MOVE.L ResErrProc, -(SP) ; push error proc BNE.S StdExitOut ; if exists, return, else, ADDQ #4, SP ; pop off error proc address StdExitOut RTS ; ...and return ;_______________________________________________________________________________ ; ; Routine: HandleScan (utility) ; RestoreCache (utility ; ; Arguments: A1 (input.L) resource handle ; A2 (output.L) ptr to entry with correct handle (or nil) ; A3/A4/D3-D6 Normal setup into map where handle found ; ; Called By: (HandleScan): LoadResource, StdResEntry, RefHandle, AddResource ; (RestoreCache): GetIndResource ; Calls: GetTopMap, GetEntries, NextMap, SaveCache ; ; Function: Returns A2 pointing to entry with the correct handle, or nil if ; not found. Scans all maps. ;_______________________________________________________________________________ HandleScan MOVE.L A1, D0 ; Check for zero handle BEQ NotFound ; Can't have a zero handle, say not found CMPA.L HSCHandle,A1 ; is this handle in the cache? <12mar85> BBM BEQ.S RestoreCache ; if yes, go set regs and return HndlScan ; alternate entry for RestoreCache <18jul85> BBM BSR GetTopMap ; Point to the topmost map first MOVE.L A0,-(SP) ; save A0 across HandleScan Call <01may85> BBM @0 BSR GetEntries ; Point to the resource entries BMI.S @3 ; If no entries, link to next map. MOVE.L A3,A0 ; Keep A0 around as a pointer to types ADDQ #TSize,A0 ; point at the next type entry <20may85> BBM @2 ADDQ #2,A0 ; ... point to the next type <02may85> BBM @1 ADDQ #RHndl,A2 ; adjust A2 for speed CMPA.L (A2)+,A1 ; Is this the handle we want? DBEQ D4,@1 ; If more of this type continue <01MAY85> BBM/LAK BEQ.S @4 ; ... yes, exit with save. <01MAY85> BBM/LAK MOVE.L (A0)+,D3 ; get the type into D3 <20may85> BBM MOVE.W (A0)+,D4 ; get the total of this type into D4 <20may85> BBM DBRA D5,@2 ; if this type exists loop back else <20may85> BBM @3 BSR NextMap ; Try to link to next map BEQ.S @0 ; If there is one, scan it, otherwise MOVE.L (SP)+,A0 ; Restore A0 <01may85> BBM BRA NotFound ; the handle wasn't found. @4 SUBA #RESize,A2 ; Because A2 points to the next Rsrc entry <01may85> BBM BSR.S SaveCache ; save this entry in the cache <12mar85> BBM MOVE.L (SP)+,A0 ; Restore A0 <01may85> BBM BRA Found ; Exit with condition code = EQ RestoreCache MOVEM.L HSCache,D3/A1-A4 ; restore the long regs from cache <12mar85> BBM MOVEM.W HSCEntryCnt,D4-D6 ; restore the word regs from cache ADD.L (A4),A2 ; Make A2 a pointer ADD.L (A4),A3 ; Make A3 a pointer CMPA.L RHndl(A2),A1 ; Is this really the handle in the map? <18jul85> BBM BEQ Found ; good data means finish restoring cache <18jul85> BBM CLR.L HSCHandle ; bad data in cache so invalidate it <18jul85> BBM BRA.S HndlScan ; and go look for the real thing <18jul85> BBM ;_______________________________________________________________________________ ; ; Routine: SaveCache (utility) ; ; Arguments: A1 (input.L) handle to resource ; A2 (input.L) pointer to resource entry ; A3 (input.L) pointer to resource name ; A4 (input.L) map handle ; D3 (input.L) resource type ; D4 (input.W) current entry count (this map) ; D5 (input.W) Total count (-1) of this type ; D6 (input.W) Map/file reference number ; D0 (output.W) Gets trashed ; ; Called By: (SaveCache): GetNamedResource, GetResource, HandleScan ; (SaveIndCache): GetIndResource ; Calls: NONE ; ; Function: Saves the current resource reg world into HSCache. ;_______________________________________________________________________________ SaveCache ; MOVE.W MinusOne,GIRIndex ; invalidate GetIndResource cache <27jun85> BBM SaveIndCache ; alternate entry for GetIndResource MOVE.L (A4),D0 ; for speed get make D0 a pointer <06may85> BBM SUB.L D0,A2 ; make A2 an offset as map may move SUB.L D0,A3 ; make A3 an offset as map may move MOVEM.L D3/A1-A4,HSCache ; save long regs into the cache <12mar85> BBM MOVEM.W D4-D6,HSCEntryCnt ; save word regs into the cache <19mar85> BBM ADD.L D0,A2 ; restore A2 as a pointer ADD.L D0,A3 ; restore A3 as a pointer RTS ;_______________________________________________________________________________ ; ; Routine: NameResource (utility) ; ; Arguments: A2 (input.L) pointer to resource entry ; A0 (output.L) pointer to resource name ; ; Called By: CheckLoad, GetNamedResource, GetResInfo ; Calls: NONE ; ; Function: Returns A0 pointing to the resource name (or CC=MI if not found). ;_______________________________________________________________________________ NameResource MOVE.W RNameOff(A2), D0 ; Get the name offset BMI.S @9 ; if negative, return empty string. MOVE.L (A4), A0 ; Dereference map handle ADDA.W MNames(A0), A0 ; Jump to names block ADD.W D0, A0 ; and offset to the name BRA Found ; say found. ; if here, named resource failed. @9 LEA NullStr, A0 ; Get address of an empty string, BRA NotFound ; and say not found ;_______________________________________________________________________________ ; ; Routine: NextEntry (utility) ; ; Arguments: A2 (input.L) pointer to resource entry ; D4 (input.W) Resource entry count ; D5 (input.W) Type entry count ; A2 (output.L) pointer to next ID resource entry ; D3 (output.L) resource type (if changed) ; D4 (output.W) number of item types (if changed) ; ; Called By: CountIResources, GetNamedResource, RmveName ; Calls: NONE ; ; Function: Set up A2 as pointer to the next ID resource entry. Returns ; CC=MI if not found, CC=EQ if found, and CC=GT if changed type. ; ;_______________________________________________________________________________ NextEntry ADD.W #RESize, A2 ; Point to the next entry (sign extended) SUBQ.W #1, D4 ; Decrement resource entry count BPL Found ; Return if still more entries left SUBQ.W #1, D5 ; Decrement type entry count BMI NotFound ; If negative, hit end of map MOVE.W TypeCount(A3), D0 ; Get number of types SUB.W D5, D0 ; Get type index ASL.W #TypeShift, D0 ; *8 gives offset to the type MOVE.L TType+2(A3, D0), D3 ; Get the type in D3 MOVE.W TCount+2(A3, D0), D4 ; Get number of items in D4 MOVEQ #1, D0 ; Set CC=GT, for "typeChanged" flag RTS ; and return ;_______________________________________________________________________________ ; ; Routine: DoRomEntry (utility) <11apr85> BBM ; ; Arguments: A2 (input.L) pointer to resource entry ; A0 (output.L) handle to resource ; A1 (output.L) trashed ; D0 (output.L) trashed ; ; Called By: CheckLoad ; Calls: _HandleZone, SetPL ; ; Function: If the ROM resource has been released, "load it" back in. This ; code really just recovers what has always been there. ;_______________________________________________________________________________ DoRomEntry ; All new routine <20aug85> BBM MOVE.L A1,-(SP) ; need to preserve this regs MOVE.L RLocn(A2),D0 ; Get the offset to the ROM rsrc AND.L Lo3Bytes,D0 ; Get rid of the Attrs ADD.L RomBase,D0 ; D0 now points to the ROM Rsrc MOVE.L D0,A1 ; Save off for later MOVE.L RomMapHndl,A0 ; get a pointer to the start of ROZ Zone _HandleZone ; MOVE.L -4(A1),D0 ; Rel handle may have useful hi byte AND.L Lo3Bytes,D0 ; Restrict to 24MB range off header ADDA.L D0,A0 ; Add in offset to MP [-4(A1) is the RelHandle] MOVE.L A0,RHndl(A2) ; map gets handle to the rsrc TST.B ResLoad ; test if we want to stuff MP BEQ.S @9 ; CC=EQ means just allocate handle MOVE.L A1,(A0) ; stuff MP with pointer to rsrc in ROM <29aug85> BBM BSR SetPL ; set the Purgable/Lock bits in MP @9 MOVE.L (SP)+,A1 ; restore regs <29aug85> BBM RTS ; and exit ******************************************************************************************** ; Rolled in decompression stuff from DecompressorPatch.a 4/14/92 stb ; ; To Do: Rewrite this stuff entirely, because it is showing its organic growth and the ; logic is less clear than it could be. DecompressionLocals RECORD {a6Link},decr ;<17> return DS.L 1 a6Link DS.L 1 ResHeaderBuffer DS.B ResourceTemplate.ResTemplateSize ; room for a ExtResRecord DoDonnDecompress DS.B 1 ; boolean set if we're doing "old" decompression extra DS.B 1 ; and a little padding DefProcHandle DS.L 1 ; handy place to keep the current decompressor stb localSize EQU * ENDR ;<17> ******************************************************************************************** * * CheckLoad for decompression * * Description: If we are reading in a packed resource, then unpack the * data as it is loaded. * * New * Operation: If the resource is not compressed, * or if the handle has data then Jump PlainOldCheckLoad. * Remember ResLoad, Clear ResLoad. * Call PlainOldCheckLoad to allocate the data handle. * Restore ResLoad, if False then exit. * Allocate the data handle (in the right heap), with a * little extra slop (using resrvemem if locked). * Unpack the data in place. * Trim away the extra slop. * Exit. * * Input: A2: pointer to resource list entry * A4: resource map handle * * ResLoad: true if load, false if no load * * Output: A0: handle to resource * A1: trashed * A2-A7: unchanged * D0-D2: trashed * D3-D7: unchanged * * Called by: Resource Manager * * Register usage: D2 - offset of raw data in this resource. * D3 - handle's zone. * D4 - resource attributes. * D5 - unpacked size. * D6 - offset to this resource's data, then the var table handle. * D7 - original resLoad state. * A2/A3/A4 - as the Resource Manager needs them. * A5 - the resource handle. * A6 - LINKed locals <17> * ******************************************************************************************** CheckLoad ; moved the vectored jump up from the original checkload MOVE.L jCheckLoad,A0 ; get the vector from the OSJumptable JMP (A0) ; and go to the routine vCheckLoad ; Def to build dispatch entry ; Force all system resources into the system heap by setting the ResSysHeap bit. PN.start subq #2,sp move.l a4,-(sp) _IsThisASystemResourceMap ; Is this the system map or system override? tst.b (sp)+ bne.s @system_rsrc ; if so, branch move.l (a4),a0 ; a0 <- ptr to map btst.b #overrideNextMapBit,MAttr(a0) ; should all entries in map go in system heap? beq.s @GoOnCheckLoad ; if not, branch @system_rsrc bset #ResSysHeap,RAttr(a2) ; get into the system heap (and stay there!) bne.s @GoOnCheckLoad ; branch if was already set bset #ResSysRef,RAttr(a2) ; mark that shouldn't be permanent @GoOnCheckLoad ; PN.end ; This snippet checks to see if the resource reference entry already contains a handle ; or not. If it does, DeanBit is cleared. If there is no handle (ie, the resource will ; be loaded this time) set DeanBit. This allows people to determine whether they loaded ; a resource, or if someone else did. ; tst.l RHndl(a2) ; See if a master pointer has already been allocated bz.s @setDeanBit bclr #kDeanBit,kBrianBits ; A master pointer has already been allocated bra.s @goLoadTheResource @setDeanBit bset #kDeanBit,kBrianBits ; WeÕll be loading the resource right now @goLoadTheResource ;is it compressed? Flag that it isn't in case it gets modified and written. BTst.B #resExtended,RAttr(A2) BNZ.S TestResHandle BRA PlainOldCheckLoad ;no, then just do the old checkload stuff. ; if there is already data in the handle, then just call old checkload. TestResHandle Move.L RHndl(A2),D0 ;is the handle loaded already? BZ.S DeCompressor ;no, then we will try to load it. Move.L D0,A0 Move.L (A0),D0 ;check if the master pointer is nil BNZ PlainOldCheckLoad ; it has data, so no need to load, or decompress. DeCompressor WITH DecompressionLocals, ExtResRecord LINK A6, #localSize ; save space for a read buffer and stuff <17> MoveM.L D3-D7/A4-A5,-(SP) ;save some regs. ; Remember ResLoad, Set ResLoad False. Move.B ResLoad,D7 ;remember ResLoad. ?Should I use _GetResLoad and SetResLoad? Clr.B ResLoad ;don't load the data in old checkLoad. ; The resource is compressed but not loaded yet. Make sure the handle gets created. BSr PlainOldCheckLoad ;create the handle for the data. Move.B D7,ResLoad ;restore ResLoad. BZ.S @IfZExit2 Move.L A0,A5 ;remember the handle. Move.L A0,D0 ;is the handle allocated now? @IfZExit2 BZ Exit2 ; no, then we can't do any more. Move.B RAttr(A2),D4 ;remember the attribute flags. ; read in the resource data header. This gives us decompressed size. MoveQ #ExtResRecord.ResHeaderSize,D0 ;amount we wish to read. Move.L RLocn(A2),D6 ;get the relative data location. And.L Lo3Bytes,D6 ;mask off the resource attributes. Move.L D6,D1 ;this is where we want to start reading from. Bsr ReadResBuffer ;read in the resource data. ; do a robustness check to see if the handle really seems to be compacted. Cmp.L #RobustnessData,ExtResRecord.ResHeader.signature(A0) ;is it really an extended resource? BEQ.S @TestHeaderVersion MoveM.L (SP)+,D3-D7/A4-A5 ;restore the regs, but don't pop them yet. UNLK A6 ; <17> Bra PlainOldCheckLoad ;read in the data, now that resLoad is restored. @TestHeaderVersion Move.W #CantDecompress,D2 ;assume bad extended resource. lea DoDonnDecompress(a6), A1 ;get flag location <17> sf (a1) ;set the flag, assuming that's what we want Cmp.B #CurHeaderVersion,ResHeader.headerVersion(A0) ;is this DonnBits? BEQ @headerVersionOK ;yep, okay st (a1) ;nope, clear the flag cmp.b #greggyHeaderVersion, ResHeader.headerVersion(a0) ;is this GreggyBits? bne ErrorExit ;no, bail @headerVersionOK ;move along ; Make the pointers into the Map relative offsets, so we can rebuild them after a heap shuffle. Sub.L (A4),A2 ; pointer to map entry becomes an offset. Sub.L (A4),A3 ; some callers have a block pointer here. ; assume it's just a non-compressed extended resource, compute data size and offset. MoveQ #ExtendedResource.extendedData,D2 ;offset to start of data for a normal extended attribute resource Move.L ResSize(A0),D5 ;get the size, including header. Sub.L D2,D5 ;actual amount of data to read. BTst #resCompressed,ResHeader.extendedAttributes(A0) BZ HaveSizeAndOffset ;not compressed, then we have the size and offset. ; check which def proc to unpack it with. We use a simple robust caching scheme to avoid _GetResource calls. Move.W #badExtResource,D2 ;assume an error if it was the wrong version! btst #0, DoDonnDecompress(a6) ; are we doing DonnBits <17> bne.s @notDonn ; no, get ID from revised general header format Move.W ResHeader.decompressID(A0),D5 ;get the Donn ID this resource needs bra.s @gotID ; ...and keep going @notDonn move.w ResHeader.defprocID(a0), d5 ; get defProc @gotID ; here, we look for decompression defprocs in all files below the current one Move.W #CantDecompress,D2 ;assume bad extended resource move.l a4,a1 ;get a handle to the first file to look in @tryMap move.l a1,d0 ;are we done? bz ErrorExit ;yes, we looked and didnÕt find anything move.l (a1),a0 ;get map pointer btst #decompressionPasswordBit,mInMemoryAttr(a0) bz.s @nextFile move.w CurMap,-(sp) Move.B ResOneDeep,-(SP) ;preserve the depth setting move.w ROMMapInsert,-(sp) ;save the value of ROMMapInsert <15> move.l ResErrProc,-(sp) ;remember the ResErrProc <15> move.w mRefNum(a0),CurMap ;get resource from this file clr.w ROMMapInsert ;donÕt even think about ROM map <15> clr.l ResErrProc ;and donÕt call the app. <15> SubQ #4,SP Move.L #DeCompressDefType,-(SP) ;'dcmp' Move.W D5,-(SP) _Get1Resource ;get the decompress def. proc. Move.L (SP)+,A0 move.l (sp)+,ResErrProc ;back to normal <15> move.w (sp)+,ROMMapInsert ;restore ROM guy too <15> Move.B (SP)+,ResOneDeep ;restore depth move.w (sp)+,CurMap Move.L A0,D0 bne @gotDecompressor ;if we got the decompressor, then use it move.w ResErr,d0 ;if there was no dcmp, go on beq.s @nextFile cmp.w #resNotFound,d0 ;if there was an error, quit with the error bne ErrorExit @nextFile move.l (a1),a1 ;get map pointer move.l mNext(a1),a1 ;go on to the next file in the chain bra.s @tryMap @gotDecompressor ; remember the defproc handle. (mostly 'cause we don't have any registers left...) Lea DefProcHandle(A6),A1 ;stuff away the defproc stb Move.L A0,(A1) ;stuff away the defproc handle into DefProc ; it is a compressed resource, make sure we can handle it, and get its size from the header. @HaveDefProc Lea ResHeaderBuffer(a6),A0 ;point into our frame. <17> btst #0, DoDonnDecompress(a6) ; are we DonnBits? <17> bne.s @cTableDontCare ; no, then cTables are not used Tst.W ResHeader.cTableID(A0) ;is the built in table to be used? Bne ErrorExit ; for now, we don't load decompression tables. @cTableDontCare MoveQ #ExtendedResource.compressedData,D2 ;offset to start reading from. Move.L ResHeader.actualSize(A0),D5 ;get the unpacked size. MoveQ #0,D0 ;overRun indicates the amount of extra room we need to btst #0, DoDonnDecompress(a6) ; are we DonnBits? <17> bne.s @getWordSizedSlop ; no, then slop size is a word Move.B ResHeader.overRun(A0),D0 ; avoid the input and output pointers crossing during decompression. bra.s @addOverRun ; @getWordSizedSlop ; move.w ResHeader.decompressSlop(a0), d0 ; get word sized slop size @addOverRun ; Add.L D0,D5 ; block size must include overRun. HaveSizeAndOffset ; Remember the current heap zone, and switch to the zone of the compressed handle. MOVE.L TheZone,A0 ;get the current heap zone. Move.L A0,D3 ;remember current heap. Cmp.L RomMapHndl,A4 ; is it in the ROM map? Bne.S @NotROMMap ; then go recover information ; Break 'RomMapHndl Zone' Move.L A4,A0 _HandleZone ; use the zone that the ROM Map comes from. Bra.S @SetRightZone @NotROMMap BTst.L #ResSysHeap,D4 ; Is it in the system heap? BZ.S @SetRightZone ; No, use same heap Move.L SysZone,A0 ; otherwise set the system zone for now @SetRightZone MOVE.L A0,TheZone ; and use it, for now. ; If the handle was locked, then we reserve low memory for the bigger unpacked handle. BTst.L #resLocked,D4 ;should the handle be locked? BZ.S @DoneReserve Move.L D5,D0 ;amount of space we will need. _ResrvMem ;reserve room in locked space for the handle. @DoneReserve ; Reallocate the handle. Move.L A5,A0 Move.L D5,D7 ;remember new size. Move.L D5,D0 _ReallocHandle ;set up the unpacked handle's size. Move.W D0,D1 BZ.S @GotHandle ;did it get allocated without an error? ; Break 'Error from _ReallocHandle' Move.W D1,ResErr Suba.l A5, A5 ; return NIL since we donÕt have enough memory <10> Bra ExitCLPastHSetState ;exit if an error happened. Skip HSetState <10> @GotHandle ; compute the amount of data to be read. Move.L ResHeaderBuffer+ExtResRecord.ResSize(a6),D0 ;amount of raw resource data. <17> Sub.L D2,D0 ;subtract the (offset of data from the header) from size. ; compute where the data should go. Move.L (A5),A0 ;point to the handle base. Sub.L D0,D7 ;subtract the data size from the block size. Add.L D7,A0 ;point to the last place where the data will fit. ; Read the data into the end part of the handle. Move.L D6,D1 ;where the size and resource header start. AddQ.L #ResHeader-ResSize,D1 ; point past the size. Add.L D2,D1 ; we want to read from beyond the header. Bsr ReadResData ;read the data into the block. BZ.S @NoReadError ; do an error check. Move.W D0,ResErr ;set up res error from I/O error. ; Break 'error during read' Bra ExitCheckLoad @NoReadError ; if it is not a compressed resource, then we are done. BTst #resCompressed,ResHeaderBuffer+ExtResRecord.ResHeader.extendedAttributes(a6) ;compressed resource? <17> Beq ExitCheckLoad ; create the room for the variable table. It is a percentage of the unpacked size. btst #0, DoDonnDecompress(a6); DonnBits? <17> bne.s dontCallDonn ; no, call defProc via new and improved interface MoveQ #0,D0 ;get the ratio of var table to unpacked size. Move.B ResHeaderBuffer+ResHeader.varTableRatio(a6),D0 ;<17> Beq.S @HaveVarSize AddQ.L #1,D0 ;round up. Move.L D5,D1 ;unpacked size - is it a long? Swap D1 Mulu D0,D1 ;in case it is, scale the high word too. Swap D1 Clr.W D1 ;clear out the overflow. Mulu D5,D0 Add.L D1,D0 Lsr.L #8,D0 @HaveVarSize AddQ.L #VarTableRec.VarRecSize,D0 ;add enough room for at least one record. Move.L D0,D1 ;save var table size. _NewHandle ;get the table. Used to be a _NewPtr, but that moves the Realloc'ed handle Bne ErrorExitBlowoffHandle ;blow off the handle and return a nil handle _HLock ;donÕt let it move Move.L A0,D6 ;save var table ptr. ; Finally we are ready to decompress the data in the clone into our larger handle. Move.L (A5),A0 Add.L D7,A0 ;point to the data. Move.L A0,-(SP) ;source ptr Move.L (A5),-(SP) ;destination ptr. Move.L D6,A0 ;var table handle Move.L (A0),-(SP) ;pass var table ptr. Move.L D1,-(SP) ;pass var table size Move.L DefProcHandle(A6),A0 ;get the defproc handle. stb Move.L (A0),A0 FPCallDonnDecompress ; FlashPort hint attachment point Jsr (A0) ;call the defproc. Note: the defProc can't move memory! ; dispose of the var table handle. Move.L D6,A0 _DisposHandle ;dispose of the var table handle. bra.s cutBackCLHandle dontCallDonn pea ResHeaderBuffer+ExtResRecord.ResHeader(a6) ; header ptr <17> Move.L DefProcHandle(A6),A0 ; get the defproc handle. stb move.l (a0), a0 ; adda.w 0(a0), a0 ; move to offset of "Prepare" routine FPCallGreggyPrepare ; FlashPort hint attachment point jsr (a0) ; call defProc "Prepare" routine move.l (a5), a0 ; get start of block add.l d7, a0 ; point to the start of the data move.l a0, -(sp) ; source move.l (a5), -(sp) ; destination pea ResHeaderBuffer+ExtResRecord.ResHeader(a6) ; header ptr <17> Move.L DefProcHandle(A6),A0 ; get the defproc handle. stb move.l (a0), a0 ; adda.w 2(a0), a0 ; move to offset of "Decompress" routine FPCallGreggyDecomp ; FlashPort hint attachment point jsr (a0) ; call defProc "Decompress" routine pea ResHeaderBuffer+ExtResRecord.ResHeader(a6) ; header ptr <17> move.l DefProcHandle(A6), a0 ; stb move.l (a0), a0 ; adda.w 4(a0), a0 ; move to offset of "Done" routine FPCallGreggyDone ; FlashPort hint attachment point jsr (a0) ; call defProc "Done" routine cutBackCLHandle ; cut back the handle to get rid of the slop. Move.L ResHeaderBuffer+ExtResRecord.ResHeader.actualSize(a6),D0 ;final size. <17> Move.L A5,A0 _SetHandleSize ;shrink the handle to it's correct size. ; restore the handle state, and restore the zone. ExitCheckLoad Move.L A5,A0 ; Black magic code Donn stole from the resource manager. LSL.B #3,D4 ; Shift over lock to bit 7 in D4, purge bit to X . RoL.B #1,D4 ; Rotate Lock to bit 0 RoXR.B #2,D4 ; Rotate L & P to bits 7 & 6 Or.B #$20,D4 ; Set Resource Flag bit of D4.B And.B #$E0,D4 ; ‚lear all but LPR bits of D4.B _HGetState ; D0 <- LPR bits Is this needed? AND.B #$1F,D0 ; Clear LPR bits only OR.B D4,D0 ; Set up new LPR bits _HSetState ; MemMgr bits <- D0 ExitCLPastHSetState ; <10> Move.L D3,TheZone ; restore the zone. ; Make the offsets into the Map pointers again, so they will be valid after a heap shuffle. Add.L (A4),A2 ; pointer to map entry. Add.L (A4),A3 ; some callers have a block pointer here. Move.L A5,A0 ;return the handle. MACHINE MC68040 ; (should we cache flush on all cpus?) <18> ; (if we do then make sure to save D1 since trashed by '030 flush routine) <18> cmp.b #cpu68040,CPUFlag ; check if we are on a 68040 <18> bne.s flushNot040 ; If we are then <18> FPCallCacheFlush ; FlashPort hint attachment point jsr ([jCacheFlush]) ; flush data cache for consistency! <18> ; we should really do this cache line by line for speed... maybe later <18> flushNot040 MACHINE MC68000 Exit2 MoveM.L (SP)+,D3-D7/A4-A5 UNLK A6 ; <17> Rts ; We got an error cloning the handle, or creating the unpacked handle. Toss the clone (even if Nil). ErrorExitBlowoffHandle Move.W #MemFullErr,D2 ;not enough to allocate var table Move.L A5,A0 _DisposeHandle ErrorExit ;*** Break 'DeCompressor - not enough RAM - set up the error code for the Resource Man' Move.W D2,ResErr ;set up the error code for the Resource Man. Sub.L A0,A0 ;return with nil. Bra.S Exit2 ENDWITH ******************** end of stb rollin ************************************ ;_______________________________________________________________________________ ; ; Routine: PlainOldCheckLoad (utility) renamed stb ; ; Arguments: A2 (input.L) pointer to resource entry ; A0 (output.L) handle to resource ; A1 (output.L) trashed ; D0 (output.L) trashed ; D1 (output.L) trashed ; D2 (output.L) trashed ; ; Called By: Preload, Preload2, UpdateResFile, GetIndResource, GetResource, ; GetNamedResource, LoadResource ; Calls: RdRsrc, SetPL, _NewHandle, _NewEmptyHandle, SizeRsrc, ; _ResrvMem, _ReallocHandle ; ; Function: Initializes the handle, first-time if needed, and loads in if ; ResLoad is true. ; ; In the case of a reference being loaded, branch to CheckRefLoad. ; ; In the non-reference case, A2 & A3 are made offsets and restored ; after the call -- therefore they are preserved and correct. ;_______________________________________________________________________________ ; ; LoadIt, PrepHandle, GotHandle, LoadRes, ErrLoad, NoResLoad, EndLoad, EndLoad2 ; are really local labels, but the code is so twisted it is hard to tell that ; these are all part of CheckLoad. ;_______________________________________________________________________________ PlainOldCheckLoad MOVE.B RAttr(A2), D1 ; Get resource info from RAttr CMP.L RomMapHndl,A4 ; is it in the ROM map? <10apr85> BBM BEQ.S DoRomEntry ; then go recover information MOVE.L theZone, -(SP) ; Save old zone BTST #ResSysHeap, D1 ; Is it in the system heap? BEQ.S @1 ; No, use same heap MOVE.L SysZone, theZone ; otherwise set the system zone for now @1 MOVE.L RHndl(A2), A0 ; Get the handle in A0, if any. SUB.L (A4), A3 ; Make A3 an offset TST.B ResLoad ; should the resource be loaded, if nec.? BEQ.S NoResLoad ; no, just create empty handle, if needed. MOVE.L A0, D0 ; Is there a handle yet? BNE.S GotHandle ; If so, go on BSR.S PrepHandle ; Set up size, reserve mem if necessary. _NewHandle ; create a handle of the right size BEQ.S LoadRes ; if successful, load it, else BRA.S ErrLoad ; exit with error. PrepHandle BSR SizeRsrc ; get the size of the resource in D0. MOVE.L D0, D2 ; Save D0=length for routine RdRsrc. <09mar85> BBM SUB.L (A4), A2 ; Make A2 an offset. BTST #ResLocked, D1 ; Is this going to be a locked handle? BEQ.S @2 ; No, allocate as usual, floating in heap. _ResrvMem ; reserve low memory for the locked handle ; (Save/restore A0 across call! .WORD $A040) @2 MOVE.L D2, D0 ; restore D0 for memory mgr call <09mar85> BBM RTS ; and return. GotHandle TST.L (A0) ; is resource already in? BNE.S EndLoad ; if so, just return, otherwise BSR.S PrepHandle ; Set up size, reserve mem if necessary, _ReallocHandle ; and reallocate it to correct size. BMI.S ErrLoad ; if unsuccessful, don't try to load. ; RELOAD the resource, or possibly LOAD it for the first time. LoadRes ADD.L (A4), A2 ; Restore A2 MOVE.L A0, RHndl(A2) ; Set RHndl(A2) for RdRsrc BSR RdRsrc ; read the resource. BSR.S SetPL ; set purgable, lock bits in MP MOVE.W ResErr, D0 ; was there a read error? (D0 for errLoad) BEQ.S EndLoad ; If not, everything is ok. A2 correct. SUB.L (A4), A2 ; Make A2 an offset again for ErrLoad ErrLoad MOVE.W D0, ResErr ; Report error SUB.L A0, A0 ; Zero handle BRA.S EndLoadA2 ; and restore A2. ; ResLoad is FALSE. If there is already a handle, return, ; ... else allocate new. NoResLoad MOVE.L A0, D0 ; Otherwise test the handle BNE.S EndLoad ; If there is one, just return. A2 correct. SUB.L (A4), A2 ; Make A2 an offset for NewHandle call. _NewEmptyHandle ; Create a handle for load next time <07mar85> BBM EndLoadA2 ADD.L (A4), A2 ; Finally restore A2. EndLoad MOVE.L A0, D0 ; Is there a good handle? BEQ.S @1 ; If not, don't write in map MOVE.L A0, RHndl(A2) ; otherwise copy it in Hndl location @1 ADD.L (A4), A3 ; Restore A3 for caller MOVE.L (SP)+, theZone ; Restore the zone RTS ; ...and return ;_______________________________________________________________________________ ; ; Routine: SetPL (utility) ; ; Arguments: A0 (input.L) handle to resource in memory ; D1 (input.B) Resource Attribute Byte ; D1 (output.B) purgeable, lock bits ; ; Called By: CheckLoad, DoROMEntry ; Calls: NONE ; ; Function: Set purgeable, lock, and resource bits in master pointer. D0 is ; trashed, high 3 bits of Ņmaster pointerÓ are set. ;_______________________________________________________________________________ SetPL LSL.B #3, D1 ; Shift over lock to bit 7 in D1, ; purge bit to X . ROL.B #1, D1 ; Rotate Lock to bit 0 ROXR.B #2, D1 ; Rotate L & P to bits 7 & 6 OR.B #$20, D1 ; Set Resource Flag bit of D1.B AND.B #$E0, D1 ; ‚lear all but LPR bits of D1.B _HGetState ; D0 <- LPR bits AND.B #$1F,D0 ; Clear LPR bits only OR.B D1,D0 ; Set up new LPR bits _HSetState ; MemMgr bits <- D0 RTS ; finally return. ;_______________________________________________________________________________ ; ; Routine: SizeRsrcDecomp (utility) kc ; ; Arguments: A2 (input.L) pointer to resource entry ; D0 (output.L) size of resource ; ; Called By: SizeResource kc ; Calls: RREntry, ReadRsrcLength kc ; ; Function: Returns the size of the resource in D0 by reading the size word ; from the resource file. If memory manager error, sets ResErr. ; ; If the resource is marked in the map as compressed, stb ; then ; check the extended header. ; If it has a valid header ; then ; read the actual length from the header. ;_______________________________________________________________________________ SizeRsrcDecomp ; kc ; start of stb rollin from DecompressorPatch.a WITH DecompressionLocals, ExtResRecord MOVEM.L D1-D2/A0-A1, -(SP) ; Save regs BSR RREntry ; Smashes changed, added bits. BTst.B #resExtended,RAttr(A2) ; is this an extended resource? Bz.S ReadRsrcLength ; nope, treat it normally. kc @CompressedRead ; make sure this is really a compressed resource by reading in the header data, and testing for our signature. LINK A6, #localSize ; allow for reentrancy MoveM.L D1/A0,-(SP) ; save some scratch regs MoveQ #ExtResRecord.ResHeaderSize,D0 ; amount we wish to read. Move.L RLocn(A2),D1 ; get the relative data location. And.L Lo3Bytes,D1 ; mask off the resource attributes. Bsr ReadResBuffer ; read in the resource data. ; do a robustness check to see if the handle really seems to be compacted. Cmp.L #RobustnessData,ResHeader.signature(A0) ;is it really an extended resource? MoveM.L (SP)+,D1/A0 UNLK A6 BNE.S ReadRsrcLength ;didn't match, then just do old sizersrc. kc ; adjust the position offset to point within the header to the actual length. MoveQ #ExtResRecord.ResHeader.actualSize,D0 ;get delta to the new position. Add.L D0,d2 ;bump the offset by our header and a long. bra.s ReadRsrcLength ; kc ; end of stb rollin ENDWITH ;_______________________________________________________________________________ ; ; Routine: SizeRsrc (utility) ; ; Arguments: A2 (input.L) pointer to resource entry ; D0 (output.L) size of resource ; ; Called By: CheckLoad, RdRsrc, UpdateResFile, SizeResource ; Calls: RREntry, RdData ; ; Function: Returns the size of the resource in D0 by reading the size word ; from the resource file. If memory manager error, sets ResErr. ;_______________________________________________________________________________ SizeRsrc MOVEM.L D1-D2/A0-A1, -(SP) ; Save regs BSR.S RREntry ; Smashes changed, added bits. ReadRsrcLength ; kc SUBQ.L #LenWdLen, SP ; Save space for length longword MOVE.L SP, D1 ; Point buffer to stack MOVEQ #LenWdLen, D0 ; Read 4 bytes BSR RdData ; and read the bytes in! <> <30may85> BBM MOVE.L (SP)+, D0 ; Get length in D0 MOVEM.L (SP)+, D1-D2/A0-A1 ; Restore regs RTS ; ...and return. ;_______________________________________________________________________________ ; ; Routine: ReadResBuffer, ReadResData (utility) ; ; Entry: D0 - number of bytes to read. ; D1 - relative data location within the resource data block. ; A0 - pointer to the data buffer [ReadResData only]. ; A4 - resource map handle. ; A6 - LINKed locals for decompression ; Exit: D0 - result code. ; A0 - pointer to the header data. ; all other registers saved. ; ; Called By: SizeRsrc: ReadResBuffer ; ??? : ReadResData ; Calls: _Read ; ; Function: Read resource data for D0 bytes into the buffer (A0). ; ReadResBuffer uses a buffer on the stack in the A6 link. ; ; Rolled in from DecompressorPatch.a stb ;_______________________________________________________________________________ With ExtendedResource, ExtResRecord, VarTableRec, ResourceTemplate, DecompressionLocals ReadResBuffer Lea ResHeaderBuffer(a6),A0 ; <17> ReadResData MoveM.L D1-D2/A0-A3,-(SP) MoveQ #ioQElSize,D2 ;create a param block on the stack. Sub.L D2,SP Move.L A0,ioBuffer(SP) ;place to put the data. Move.L SP,A0 ;for the read call. Move.L (A4),A1 ;deref the map handle. Move.W MRefNum(A1),ioRefNum(A0) ;refNum from the resource map. Move.L D0,ioReqCount(A0) ;number of bytes to read. Move.W #1,ioPosMode(A0) ;read from start of file. Add.L ResDataOffset(A1),D1 ;add the base data offset in the file. Move.L D1,ioPosOffset(A0) ;computed offset from file start. _Read ;read the resource data. Add.L D2,SP ;strip the ioParam block. MoveM.L (SP)+,D1-D2/A0-A3 Rts ;_______________________________________________________________________________ ; ; Routine: RdRsrc, RRExit (utility) ; ; Arguments: A2 (input.L) pointer to resource entry ; D2 (input.L) Size of Resource ; ; Called By: (RdRsrc): CheckLoad ; (RRExit): WrRsrc ; Calls: RREntry, SizeRsrc, RdData ; ; Function: Loads the resource into the handle specified in RHndl(A2). The ; handle MUST be the correct size. ;_______________________________________________________________________________ RdRsrc MOVEM.L D0-D2/A0-A1, -(SP) ; Save regs MOVE.L D2,D0 ; get rsrc size into D0 for RdData <09mar85> BBM BSR.S RREntry ; Set up the regs for read/write ADDQ.L #LenWdLen, D2 ; Skip over the length longword MOVE.L (A1), D1 ; Set buffer address BSR RdData ; and read the bytes in! <> <30may85> BBM CSS RRExit MOVEM.L (SP)+, D0-D2/A0-A1 ; Restore registers ... RTS ; ...and return! ;_______________________________________________________________________________ ; ; Routine: RREntry (utility) ; ; Arguments: A2 (input.L) pointer to resource entry ; A4 (input.L) handle to resource map ; A0 (output.L) pointer to resource map ; A1 (output.L) handle to resource ; D2 (output.L) location of entry in file ; ; Called By: SizeRsrc, RdRsrc, WrRsrc ; Calls: NONE ; ; Function: Given a resource entry pointer, set up registers for read/write ;_______________________________________________________________________________ RREntry ANDI.B #RCBMask, RAttr(A2) ; Clear resChanged on read/write. RREntry6 ; <9> rb MOVE.L (A4), A0 ; Dereference map handle again MOVE.L RLocn(A2), D2 ; Get location long word AND.L Lo3Bytes,D2 ; Clear high 8 bits. ADD.L ResDataOffset(A0), D2 ; Add in the data offset MOVE.L RHndl(A2), A1 ; Get the handle in A1 RTS ; ...and return. ;_______________________________________________________________________________ ; ; Routine: WrRsrc (utility) ; ; Arguments: D2 ; A2 (input.L) pointer to resource entry ; A4 (input.L) handle to map ; ; Called By: UpdateResFile, WrRsrc ; Calls: RREntry, _GetHandleSize, WrData, RRExit ; ; Function: Writes resource specified in RHndl(A2) out to the resource file ;_______________________________________________________________________________ WrRsrc MOVEM.L D0-D2/A0-A1, -(SP) ; Save regs BSR.S RREntry ; Set up the regs for read/write MOVE.L A1, A0 _GetHandleSize ; Get the size to write out TST.L D0 ; for sizes bigger than 32k <15mar85> BBM BPL.S @1 ; if good size, go on, else MOVEQ #0, D0 ; force zero length (purged!) @1 MOVE.L D0, -(SP) ; Push size on the stack MOVE.L SP, D1 ; Write the size out (buffer addr.=stack) MOVEQ #LenWdLen, D0 ; Write 4 bytes BSR.S WrData ; Write out length word data (was WrData2) <30may85> BBM ADDQ.L #LenWdLen, D2 ; Skip over length longword MOVE.L (A1), D1 ; Read bytes from handle MOVE.L (SP)+, D0 ; Restore the size to D0 for write BSR.S WrData ; ...and do it! (was WrData2) <30may85> BBM BRA.S RRExit ; Restore regs and exit. ;_______________________________________________________________________________ ; ; Routine: SetFileIO (utility) ; ; Arguments: A6 (input.L) LINK'ed for file I/O ; D0 (input.L) number of bytes to read/write ; D1 (input.L) IO buffer address ; D2 (input.L) IO position offset ; D6 (input.W) IORefnum ; A0 (output.L) pointer to IO stack frame ; ; Called By: RdData, WrData, SetRFEOF, CheckGrow, NewMap, CreateResFile, ; CloseResFile ; Calls: NONE ; ; Function: Points A0 to the I/O Stack Frame, and fills out the Param Block ; from imput registers. ;_______________________________________________________________________________ SetFileIO WITH ResourceMgrStack ; stb LEA ioBlock+IORefNum(A6), A0 ; Point to frame at IORefNum stb MOVE.W D6, (A0)+ ; Set IORefnum ADDQ #6, A0 ; Skip over unused stuff MOVE.L D1, (A0)+ ; Set IOBuffer MOVE.L D0, (A0)+ ; Set IOByteCount ADDQ #4, A0 ; Skip actual byte count MOVE.W #1, (A0)+ ; Set IOPosMode=absolute (fsFromStart) MOVE.L D2, (A0)+ ; and finally set IOPosOffset. LEA ioBlock(A6), A0 ; Reset A0 for stack frame RTS ; and return. ENDWITH ; stb ;_______________________________________________________________________________ ; ; Routine: SetFileIODirID (utility) ; ; Arguments: A6 (input.L) LINK'ed for file I/O ; D0 (input.L) number of bytes to read/write ; D1 (input.L) IO buffer address ; D6 (input.W) IORefnum ; A0 (output.L) pointer to IO stack frame ; ; Called By: RdData, WrData, SetRFEOF, CheckGrow, NewMap, CreateResFile, ; CloseResFile ; Calls: NONE ; ; Function: Just like SetFileIO except don't trash ioDirID w/ a posOffsetÉ ;_______________________________________________________________________________ SetFileIODirID WITH ResourceMgrStack ; stb LEA ioBlock+IORefNum(A6), A0 ; Point to frame at IORefNum stb MOVE.W D6, (A0)+ ; Set IORefnum ADDQ #6, A0 ; Skip over unused stuff MOVE.L D1, (A0)+ ; Set IOBuffer MOVE.L D0, (A0)+ ; Set IOByteCount ADDQ #4, A0 ; Skip actual byte count MOVE.W #1, (A0)+ ; Set IOPosMode=absolute (fsFromStart) LEA ioBlock(A6), A0 ; Reset A0 for stack frame RTS ; and return. ENDWITH ; stb ;_______________________________________________________________________________ ; ; Routine: RdData (utility) ; ; Arguments: A6 (input.L) LINK'ed for file I/O ; D0 (input.L) number of bytes to read/write ; D1 (input.L) IO buffer address ; D2 (input.L) IO position offset ; D6 (input.W) IORefnum ; A0 (output.L) pointer to IO stack frame ?? ; ; Called By: SizeRsrc, RdRsrc, NewMap ; Calls: SetFileIO, _Read, IOExit ; ; Function: Read data according to input registers. Note A2/A3 made offsets ; across this call and resored in IOExit ;_______________________________________________________________________________ RdData BSR.S SaveRegs ; Saves A1/A0/D1/D0 and makes A2/A3 offsets <22aug85> BBM ; so their handles can move across _Read stb BSR.S SetFileIO ; Set up a file frame _Read ; Read the bytes BRA.S IOExit ; sets reserr and restores all ;_______________________________________________________________________________ ; ; Routine: WrData, WrDataSt (utilities) ; ; Arguments: A2,A3 (not used) May get blitzed!! (see Warning below) ; A4 (not used) handle to Map ; A6 (input.L) LINK'ed for file I/O ; D0 (input.L) number of bytes to read/write ; D1 (input.L) IO buffer address ; D2 (input.L) IO position offset ; D6 (input.W) IORefnum ; A0 (output.L) pointer to IO stack frame ; ; Called By: (WrData): WrRsrc, UpdateResFile, UpdateResFile, CreateResFile ; (WrDataSt): CreateResFile ; (IOExit): WrData, RdData, SetRFEOF ; (RestRegs): SetRFEOF ; Calls: SetFileIO, _Write, WrData ; ; Function: Write Data to file according to input registers. This write ; may move map around in the heap, so A2/A3 pointers are always ; saved across this call (by making them offsets). ; ; NOTE: IOExit and RestRegs are the standard returns for RdData, WrData, ; and SetRFEOF. Also note that IOExit stuffs result in ResErr. ;_______________________________________________________________________________ WrDataSt MOVEQ #0, D2 ; PosOffset=0 WrData BSR.S SaveRegs ; Saves A1/A0/D1/D0 and makes A2/A3 offsets <22aug85> BBM BSR.S SetFileIO ; Set up a file frame _Write ; Write the bytes IOExit MOVE.W D0, ResErr ; Save file I/O result in ResErr RestRegs ADDA.L (A4),A3 ; restore A3 to a pointer <30may85> BBM ADDA.L (A4),A2 ; restore A2 to a pointer <30may85> BBM MOVEM.L (SP)+, A0-A1/D0-D1 ; Restore regs <22aug85> BBM RTS ; ...and return ;_______________________________________________________________________________ ; ; Routine: SaveRegs (utility) ; ; Arguments: A4 (input.L) handle to a map ; ; Called By: RdData, WrData, WrDataSt, SetRFEOF, CheckGrow ; Calls: NONE ; ; Function: Standard entry routine that saves A0/A1/D0/D1, and makes A2/A3 ; into offsets. The reverse operation is RestRegs. Note that A4 ; must be even else an address error occurs. ;_______________________________________________________________________________ SaveRegs MOVEM.L A0/D0/D1,-(SP) ; Stack now has return address and A0/D1/D0 <22aug85> BBM MOVE.L 12(SP),A0 ; Get return address into A0 for return. MOVE.L A1,12(SP) ; Stack now has A1/A0/D1/D0. SUBA.L (A4),A3 ; make A3 an offset SUBA.L (A4),A2 ; make A2 an offset JMP (A0) ; ... and return ;_______________________________________________________________________________ ; ; Routine: SetRFEOF (utility) ; ; Arguments: A4 (input.L) handle to a map ; ; Called By: UpdateResFile, ResizeMap, AllocRes, ReallocRes ; Calls: ResRW, SetFileIO, _SetEOF ; ; Function: Set the resource file EOF, and now (14aug85) checks if map is in ; front or in back of the data. ;_______________________________________________________________________________ SetRFEOF BSR.S SaveRegs ; Saves A1/A0/D1/D0 and makes A2/A3 offsets <22aug85> BBM SetEOF2 BSR ResRW ; Read/write allowed? BNE.S RestRegs ; if not, just exit! <22aug85> BBM BSR.S SetFileIO ; Set up a file block BSR.S MaxRFEOF ; get the end of the file <14aug85> BBM MOVE.L D0,IOLEOF(A0) ; Set EOF in parameter block _SetEOF ; call the FS BRA.S IOExit ; and exit through common code MaxRFEOF MOVEM.L A1/D1,-(SP) ; save A1/D1 across call <11sep85> BBM MOVE.L (A4),A1 ; Dereference map handle <14aug85> BBM MOVE.L (A1)+,D0 ; Get ResDataOffset into D0 <11sep85> BBM MOVE.L (A1)+,D1 ; Get ResMapOffset into D1 ADD.L (A1)+,D0 ; add in the DataSize to D0 ADD.L (A1)+,D1 ; add in the MapSize to D1 CMP.L D1,D0 ; which is greater?? BPL.S @9 ; CC=PL means ResDataOffset + DataSize = EOF MOVE.L D1,D0 ; ... else ResMapOffset + MapSize = EOF @9 MOVEM.L (SP)+,A1/D1 ; restore A1/D1 RTS ; and return ;_______________________________________________________________________________ ; ; Routine: GetHS (utility) ; ; Arguments: A2 (input.L) pointer to entry ; D0 (output.L) size of resource entry + 4 ; ; Called By: ReallocRes, AllocRes ; Calls: _GetHandleSize ; ; Function: Get ResourceSize+4 in D1 ;_______________________________________________________________________________ GetHS MOVE.L RHndl(A2), A0 ; Get the resource handle from A2 _GetHandleSize ; Get the size of the handle. ADDQ.L #LenWdLen, D0 ; add 4 for length longword <06may85> BBM MOVE.L D0, D1 ; Copy to D1 for caller. RTS ;_______________________________________________________________________________ ; ; Routine: SpaceAt (utility) ; ; Arguments: A2 (input.L) pointer to resource entry ; D0 (output.L) space available for map ; CCR (output) BMI for last resource or just before map ; ; Called By: (SpaceAt): ReallocRes ; (SpaceAt2): MaxSizeRsrc ; Calls: NextRes ; ; Function: Given A2 pointing to a resource entry, return space available in ; the map for the resource in D0. Does not include space for a ; length longword. ; If last resource, returns MI with D0=space available before map. ; Otherwise returns PL with D0=space avail before next resource. ;_______________________________________________________________________________ SpaceAt ; completely redid routine <27aug85> BBM MOVEM.L A0-A2/D1/D7,-(SP) ; Save regs MOVE.L RLocn(A2),D7 ; Get the location longword AND.L Lo3Bytes,D7 ; AND off high 8 bits. MOVE.L (A4),A0 ; dereference map to get at offsets MOVE.L ResMapOffset(A0),D0 ; check to see who is in front SUB.L ResDataOffset(A0),D0 ; ... and get delta in D0/A1 with CC's MOVE.L D0,A1 ; ... Save for later BMI.S @2 ; CC=MI means map is in front of all RSRCs CMP.L D7,A1 ; Is current resource past the map? BMI.S @2 ; CC=MI means first resource past map ; RSRC is before the map . .. BSR ZNextRes ; Get following resource--D0 is location. BMI.S @1 ; If no next resource go get size before map CMPA.L D0,A1 ; If next resource before map ... BPL.S satNotLast ; ... CC=PL means it is before map @1 MOVE.L A1,D0 ; Else get biased offset to map in D0 BRA.S satLast ; and exit though satLast ; we come here if RSRC is past map . . . @2 BSR ZNextRes ; Get following resource--D0 is location. BPL.S satNotLast ; CC=PL means next resource exists BSR.S MaxRFEOF ; get EOF in D0 and exit through satLast SUB.L ResDataOffset(A0),D0 ; make D0 an offset into the data segment <28oct85> BBM satLast ; last RSRC before Map or EOF SUB.L D7,D0 ; Get the space available into D0 MOVEQ #-1,D7 ; Set CC's to MI to tag as 'last' b4 map or LEOF BRA.S satReturn ; and exit though satReturn satNotLast SUB.L D7,D0 ; Get the space available into D0 satReturn MOVEM.L (SP)+,A0-A2/D1/D7 ; Restore regs RTS ;_______________________________________________________________________________ ; ; Routine: ReallocRes, AllocRes (utilities) ; ; Arguments: A2 (input.L) pointer to source entry ; A0 (output.L) Blitzed ; D0 (output.L) Blitzed ; D1 (output.L) Blitzed ; ; Called By: (ReallocRes): ChangedResource ; (AllocRes): AddResource ; Calls: GetHS, SpaceAt, SetRFEOF, MaxRFEOF ; ; Function: Allocate a space for the resource in the resource file. If the ; current location is ok, just return. If the current location is ; too small, allocate the resource on the end, updating the ; ResMapOffset and DataSize. WARNING!! THE RESOURCE MUST BE IN ; MEMORY. The resfile may be trashed if not. ; ; AllocRes just bypasses the SpaceAt check, and automatically ; allocates the resource at the end. Does not grow the resource ; file--assumes a previous call to CheckGrow. ;_______________________________________________________________________________ ReallocRes BSR.S GetHS ; Get handleSize+4 in D1 BSR.S SpaceAt ; How much space available here? CMP.L D0, D1 ; If space exists at end ... <27aug85> BBM BLE SetRFEOF ; ... just exit through SetRFEOF AllocRes BSR.S GetHS ; Get handleSize+2 in D1 BSR.S MaxRFEOF ; get end of rsrc file in D0 <27aug85> BBM MOVE.L (A4),A0 ; Dereference map handle <10oct85> BBM SUB.L ResDataOffset(A0),D0 ; get new data size in D0 <10oct85> BBM MOVE.B RLocn(A2),-(SP) ; save off attrs <10oct85> BBM MOVE.L D0,RLocn(A2) ; get new address <10oct85> BBM MOVE.B (SP)+,RLocn(A2) ; restore attrs <10oct85> BBM ADD.L D1,D0 ; Get new end of file <10oct85> BBM MOVE.L D0,DataSize(A0) ; ... and save it <10oct85> BBM ORI.B #MCCMask,MAttr(A0) ; Set mapChanged and MapCompact bits BSR UpdateOverriddenChangedBits ; set the changed bit for any files that may be overridden by the map in A4 BRA SetRFEOF ; exit through SetRFEOF. ;_______________________________________________________________________________ ; ; Routine: ResRW (utility) ; ; Arguments: A4 (input.L) map handle ; ; Called By: SetRFEOF, CheckGrow, UpdateResFile, WriteResource ; Calls: NONE ; ; Function: Check the read-only bit (in map attribute byte) and return CC. ;_______________________________________________________________________________ ResRW MOVE.L (A4), A0 ; Dereference map handle BTST #MapReadOnly, MAttr(A0) ; Set CC's RTS ; and return. ;_______________________________________________________________________________ ; ; Routine: CheckGrow (utility) ; ; Arguments: D6 (input.W) resource file refnum ; A1 (input.L) handle to resource to be added to the ; resource file ; ; Called By: ChangedResource, SetResInfo, AddResource ; Calls: _GetHandleSize, _SetHandleSize, ResRW, SetFileIO, _GetEOF, ; _SetEOF ; ; Function: CheckGrow checks for the DiskFull and MemFull conditions. It ; assumes the maximum overhead for adding the information to the ; map, as well as adding the data to the resource file. 256 bytes ; for max name size, 12 for the resource entry, and 6 for the type ; entry for a maximum delta of 274 bytes for the map. If the ; resource is added to the end of the resource file, the amount ; that the resource file may need to grow, worst case, will be ; 4+sizeOfResource+274 bytes. For convenience, 280+sizeOfResource ; will be used. ; ; If the resource file in question is read-only, the diskFull test ; will not be performed. Be aware of this feature. ; ; If it is safe to grow both the map handle in memory and the ; resource file on disk, CheckGrow will return with CC=EQ, and ; ResErr=0. If either the memFull or DiskFull conditions occur, ; CheckGrow will return with CC=MI and ResErr=the error code. ; ; Keeps A2,A3 correct ptrs (calculates and restores with offsets). ; Other registers, if pointing inside the map block, may become ; invalid due to the SetHandleSize moving the block. ;_______________________________________________________________________________ CheckGrow BSR SaveRegs ; Saves A1/A0/D1/D0 and makes A2/A3 offsets <22aug85> BBM MOVE.L D2,-(SP) ; Save D2 <22aug85> BBM MOVEQ #70, D1 ; Get D1=70, then ASL.W #2, D1 ; *4=280, max overhead possible. MOVE.L A4, A0 ; Get map handle in A0 _GetHandleSize ; Get the size MOVE.L D0, D2 ; Save size in D2 ADD.L D1, D0 ; Increase by max overhead _SetHandleSize ; Grow it EXG D0, D2 ; Get old size, save error code in D2 _SetHandleSize ; and shrink it back. MOVE.W D2,D0 ; Was there an error by first SetHandleSize <26aug85> BBM BMI.S CG9 ; if so, set resErr on exit, D2=code. <9> rb BSR.S ResRW ; Read/write allowed? BNE.S CG9 ; if not, exit without doing diskFull check. <9> rb MOVE.L A1, D0 ; is there a handle to account for? BEQ.S CG1 ; if not, don't add length... <9> rb MOVE.L A1, A0 ; Copy to A0 for GetHandleSize call _GetHandleSize ; get the handle size in D0 MOVE.L D0,D2 ; Test long word for error BMI.S CG9 ; if so, report error <9> rb ADD.L D0, D1 ; otherwise add length to other overhead CheckGrowAt1 ; <9> rb rb CG1 BSR SetFileIO ; Set up the file frame <9> rb LEA IOLEOF(A0), A1 ; A1 points to EOF loc'n _GetEOF ; Get the current EOF MOVE.L (A1), D2 ; Copy it to D2. ADD.L D1, (A1) ; increment it by maximum grow value ; and set it back. was it successful? ; Roll in ValidateFileSizeInCheckGrow from ResourceMgrExtensions.a TST.B (A1) ; get new size of file set up by CheckGrow (a1 points to ioLEOF inside param block) ; note: 16 meg = $01000000, so if any bits are set in first byte itÕs >= 16 meg BNE CheckGrowErr ; it's ³ 16Meg so return an error SM9> _SetEOF ; set it back CG9 ; <9> rb MOVE.L (SP)+,D2 ; restore D2 <26aug85> BBM BRA IOExit ; exit by setting CC's and ResErr <26aug85> BBM CheckGrowErr MOVE.W #EOFERR,D0 ; not really an eofErr, but it is the end of the resource fork BRA CG9 ; SM9> ;_______________________________________________________________________________ ; ; Routine: CheckMap (utility) ; ; Arguments: A4 (input.L) map handle ; D0 (output.L) Error result ; CC's (output.CC) MI=error; EQ=good ; ; Called By: OpenResFile ; Calls: NONE ; ; Function: Check the consistency of the map. This is some simple error ; checking for resource files. It preserves all regs except D0, ; and returns the error result in D0 and CC's. ; note: ; test1: Check to see if the EOF is unreasonable. ; test2: Checks to see if offset to Types is odd. (If so, map is bad.) ; test3: Checks to see if MNames starts right after all the rsrc entries. ;_______________________________________________________________________________ CheckMap MOVEM.L A0-A1/D0-D1,-(SP) ; save regs MOVE.L (A4), A0 ; Dereference map handle <05sep85> BBM ;test1 BSR MaxRFEOF ; get what map thinks to be EOF (trashes A1) <14aug85> BBM CMP.L Lo3Bytes,D0 ; Shouldn't have a file longer than $FFFFFF <21aug85> BBM BGE.S @8 ; ... If EOF is bigger than we're in trouble. ;test2 BTST.B #0,MTypes+1(A0) ; check for an odd offset BNE.S @8 ; if there is an odd offset, map is bad ;test3 MOVEA.L A0,A1 ; now both A0 & A1 point to map. ADDA.W MTypes(A0),A1 ; A1 now points to type stuff MOVE.W (A1)+,D0 ; D0 = # of types minus one (TypeCount) <08may85> BBM BMI.S @1 ; if TypeCount is minus no entries MOVEQ #0,D1 ; D1 used to sum counts of types @0 ADD.W TCount(A1),D1 ; add count for this type ADDQ #1,D1 ; since TCount is really (n-1) ADDQ #TSize,A1 ; point to next type DBRA D0,@0 ; loop back for all types ; note A1 already points to first rsrc entry MULU #RESize,D1 ; make offset to end of rsrc entries ADDA.L D1,A1 ; A1 points just past rsrc entries @1 MOVE.W MNames(A0),D1 ; get name offset into D1 <08may85> BBM BGT.S @2 ; if name offset exists go test it SUBA.L A0,A1 ; else see if A1 points past end of map MOVE.L A1,D1 ; need to and off high byte AND.L Lo3Bytes,D1 ; this size should be less than mapsize CMP.L MapSize(A0),D1 ; if CC=GT then ERROR BGT.S @8 ; Goto error BRA.S @7 ; else map is good. @2 ADDA.W D1,A0 ; point A0 where names begin CMPA.L A1,A0 ; if CC=MI then error BMI.S @8 ; BMI to error, fall through to Good ;endtests @7 MOVEQ #0,D0 ; No Error BRA.S @9 ; ... and skip next instruction @8 MOVE.W #mapReadErr,ResErr ; Error return @9 MOVEM.L (SP)+,A0-A1/D0-D1 ; restore regs RTS ; and return ;=== RmgrAsm3.a Starts Here ============================================================= ;_______________________________________________________________________________ ; ; Routine: PROCEDURE LoadResource(theResource: Handle); ; ; Arguments: 20(A6) (input.L) handle to resource ; ; Called By: A-trap through dispatcher ; Calls: StdEntry, HandleScan, CheckLoad, StdZeroExit ; ; Function: Given the handle, loads the resource from its resource file, ; if necessary. Saves all registers INCLUDING A0 and D0. ; theResource is 20(A6), over fake return+A0/D0+actual return. ;_______________________________________________________________________________ LoadResource BLANKS ON STRING ASIS MOVEM.L A0-A1/D0, -(SP) ; Save extra registers ;„„„ begin temp fix ;check if resource is in ROM or not MOVE.L 16(SP),D0 ; get resource handle BEQ.S @NilHandle ; Is the handle nil PN _StripAddress ; shave off the variation code (in case its a defproc) <13> stb MOVE.L D0,A0 ; handle in A0 MOVE.L ROMBASE,A1 CMP.L (A0),A1 ; resource in ROM BHI.S @2 ; Nope CLR.W ResErr ; since we found a ROM resource, and we assume it is ok. CSS BRA.S @9 ; yes, done @2 ;„„„ end fix PEA @9 ; Fake out stdExit to return here BSR Std1Entry ; Do standard entry <22apr85> BBM MOVE.L D0,A1 ; put stripped handle in a1 <13> stb TST.L (A1) ; Was it purged? PN BNE.S @8 ; No, don't load PN BSR HandleScan ; Otherwise set up A2 to point to the entry BEQ.S @1 ; if found, go on, else MOVE.W #ResNotFound,ResErr ; Set ResErr BRA.S @8 ; and exit. @1 MOVE.B ResLoad,-(SP) ; Save current value of ResLoad ST ResLoad ; Set TRUE temporarily, forcing a load. BSR CheckLoad ; load the resource in, if needed MOVE.B (SP)+,ResLoad ; and restore the value of ResLoad @8 BRA StdZeroExit ; Fake out stdExit to not pop params. @NilHandle MOVE.W #ResNotFound,ResErr ; set ResError PN @9 ; returns here actually... MOVEM.L (SP)+,A0-A1/D0 ; Gotta restore my regs first MOVE.L (SP)+,(SP) ; Pop off handle, preserving retaddr RTS ; ...and return. ;_______________________________________________________________________________ ; ; Routine: ReleaseResource(theResource: Handle); ; ; Arguments: 8(A6) (input.L) handle to resource ; ; Called By: A-trap through dispatcher ; Calls: StdResEntry ; ; Function: Given handle, releases the resource and disposes of the handle. ; Any GetResource to the released resource will then cause a disk ; access and return a new handle. Error condition handled in ; StdResEntry. ; Do not release system override resources from ROM, since there is rb ; no way to get the back in the resource map. rb ;_______________________________________________________________________________ ReleaseResource BSR StdResEntry ; Link, save regs, scan for handle. CMPI.W #kFakeResourceOverrideMapRefNum,D6 ; is this a ROM resource ? rb BEQ.S RelExt2 ; exit if so rb BTST #ResChanged, RAttr(A2) ; is it marked to be written? BNE.S RelExt2 ; if so, can't release! So exit. <12aug85> BBM MOVE.L A1, A0 ; Copy handle to A0 _DisposHandle ; Dispose of handle RelExit ; common exit for DetachResource <12aug85> BBM CMP.L #'FONT',D3 ; Check if we should invalidate font cache <06nov85> BBM BNE.S @0 ; CC=NE means this is not a font, so skip <06nov85> BBM MOVE.L MinusOne,LastSPExtra ; ...else invalidate font cache <06nov85> BBM @0 ; CLR.L RHndl(A2) ; Clear the handle location in map only CLR.L HSCHandle ; Invalidate cache <12mar85> BBM RelExt2 ; common exit for DetachResource <12aug85> BBM BRA StdFourExit ; and exit. ;_______________________________________________________________________________ ; ; Routine: PROCEDURE DetachResource(theResource: Handle); ; ; Arguments: 8(A6) (input.L) handle to the resource ; ; Called By: A-trap through dispatcher ; Calls: StdResEntry ; ; Function: Given the handle, releases the resource only. Does NOT dispose ; of the handle. Any GetResource to the released resource will ; then cause a disk access and return a new handle. Error ; condition handled in StdResEntry. ; Do not detach system override resources from ROM, since there is rb ; no way to get the back in the resource map. rb ;_______________________________________________________________________________ DetachResource BSR StdResEntry ; Link, save regs, scan for handle. rb CMPI.W #kFakeResourceOverrideMapRefNum,D6 ; is this a ROM resource ? rb BEQ.S RelExt2 ; exit if so rb BTST #ResChanged, RAttr(A2) ; is it marked to be written? BNE.S @5 ; if so, can't detach! <03apr85> BBM MOVEA.L A1,A0 ; GentlemanÕs way to say Ņnot an rsrcÓ _HClrRBit ; BRA.S RelExit ; Common exit code <12aug85> BBM @5 MOVE.W #resAttrErr,ResErr ; mark it as an error <03apr85> BBM BRA.S RelExt2 ; and exit <12aug85> BBM ;_______________________________________________________________________________ ; ; Routine: PROCEDURE ChangedResource(theResource: Handle); ; ; Arguments: 8(A6) (input.L) handle to the resource ; ; Called By: A-trap through dispatcher ; Calls: StdResEntry, CheckGrow, ReallocRes ; ; Function: Mark the resource to be written out into the resource file. ; If protected, won't allow change to occur. If read-only flag ; set, won't do the diskFull check, though if at a later time the ; read-only flag is cleared, it will be written. Be careful! ; DiskFull may occur at that time, which will destroy your ; resource file! ResNotFound condition handled in StdResEntry. ;_______________________________________________________________________________ ChangedResource BSR.S StdResEntry ; Link, save regs, scan for handle. bsr FlushChangedFONDs ; flush 'FOND' candidate list if this is a FOND stb MOVEA.L A1,A0 ; Save state of lock/purge/res bits in D7 _HGetState ; D0 <- LPR bits MOVE.B D0,D7 ; _HNoPurge ; donÕt allow purge here (CheckGrow) BTST #ResProtected, RAttr(A2); Is it protected? (also checks if ROM) BNE.S @5 ; if so, don't allow change. <16apr85> BBM BSR CheckGrow ; Can it grow resource file + map? BMI.S @9 ; if not, just exit with error, otherwise BSET #ResChanged, RAttr(A2) ; Set the changed bit for this resource. BSR ReallocRes ; and allocate it in-place or at end. MOVE.L (A4),A0 ; dreference map handle <28jan85> BBM BSET #mapChanged,MAttr(A0) ; ***Hack! really want MapUpdate <29jan85> BBM BSR UpdateOverriddenChangedBits ; set the changed bit for any files that may be overridden by the map in A4 BRA.S @9 ; and exit <16apr85> BBM @5 MOVE.W #resAttrErr,ResErr ; mark it as an error return <16apr85> BBM @9 MOVEA.L A1,A0 ; A0 <- handle MOVE.B D7,D0 ; D0 <- saved LPR bits _HSetState ; BRA StdFourExit ; exit ;_______________________________________________________________________________ ; ; Routine: PROCEDURE WriteResource(theResource: Handle); ; ; Arguments: 8(A6) (input.L) handle to the resource ; ; Called By: A-trap through dispatcher ; Calls: StdResEntry, ResRW, WrRsrc ; ; Function: Given the handle, writes out the resource back to the resource ; file. ResChanged is checked, and the resource not written ; unless TRUE. Error condition handled in StdResEntry. ;_______________________________________________________________________________ WriteResource BSR.S StdResEntry ; Link, save regs, scan for handle. bsr FlushResourceCache BSR ResRW ; Read/write allowed on this file? BNE.S @9 ; if not, don't allow the write! BTST #ResChanged, RAttr(A2) ; test resChanged attribute BEQ.S @9 ; Don't write if not changed. BSR WrRsrc ; Else write out the changed resource ; and exit without error <12aug85> BBM @9 BRA StdFourExit ; pop 4 bytes and exit. ;_______________________________________________________________________________ ; ; Routine: StdResEntry (utility) ; ; Arguments: 8(A6) (input.L) handle to the resource ; xx (output.x) output from HandleScan ; ; Called By: ReleaseResource, DetachResource, WriteResource, HomeResFile, ; ChangedResource, SizeResource, MaxSizeRsrc, RsrcMapEntry ; Calls: Std1Entry, HandleScan, StdFourExit ; ; Function: Given the handle 8(A6), scans for the handle and exits if not ; found. StdEntry returns with A0 pointing to the last argument ; (the handle). Callers should exit through StdFourExit. ;_______________________________________________________________________________ Std2ResEntry MOVE.L MinusOne,12(SP) ; Assume it can't be found <21aug85> BBM StdResEntry MOVE.L (SP)+, D0 ; Get return address BSR Std1Entry ; Link A6, save regs <22apr85> BBM MOVE.L D0, -(SP) ; Push return back. MOVE.L A0,D0 ; Check for nil handle <22may85> BBM BEQ.S @5 ; if nil return with error <22may85> BBM MOVE.L (A0), A1 ; Get the resource handle BSR RefHandle ; Scan for it <26aug85> BBM BEQ.S @9 ; If found, just return @5 ADDQ #4, SP ; Otherwise, pop the return address BRA StdFourExit ; and exit. @9 RTS ; ... else return ;_______________________________________________________________________________ ; ; Routine: FUNCTION HomeResFile(theResource: Handle): INTEGER; ; ; Arguments: 8(SP) (input.L) handle to the resource ; 12(A6) (output.W) refnum of resource file that has handle ; ; Called By: A-trap through dispatcher ; Calls: StdResEntry, StdFourExit ; ; Function: Given a handle, returns the refnum of the resource file that the ; resource lives in. If the resource is not found, returns -1. ; Error condition handled in StdResEntry. ;_______________________________________________________________________________ HomeResFile MOVE.W #-1,8(SP) ; Assume failure. <06may85> BBM BSR.S StdResEntry ; Get the resource, and return if NIL. CMP.W SysMap, D6 ; Is it the system or rom map? <16may85> BBM BNE.S @1 ; No, leave refnum, @0 MOVEQ #0, D6 ; else return 0 for homeResFile value. @1 MOVE.W D6, 12(A6) ; Return map refnum as function result BRA StdFourExit ; and exit. ;_______________________________________________________________________________ ; ; Routine: PROCEDURE SetResPurge(install: BOOLEAN); ; ; Arguments: 8(A6) (input.W) Install flag ; ; Called By: A-trap through dispatcher ; Calls: _WriteResource (later in purge proc) if a resource gets purged ; and has been marked changed ; ; Function: Install or remove the resource manager purge hook in the ; current zone. ; ; Clearing now means leaving the disk cache purge proc in place. ; Setting now means putting RPHook into the purge proc, and it ; calls through to the the TrueType disk cache purge proc. stb ;_______________________________________________________________________________ IMPORT DiskCachePurgeProcedure ;------ start of the resource mgr purge proc ; The actual purge hook code. Assumes the handle is pushed on stack. ; Smashes A0, A1 and D0 always. RPHook move.l 4(sp),-(sp) jsr DiskCachePurgeProcedure ; Give TrueType a crack at flushing this block stb ; to disk if itÕs a font cache block stb MOVE.L (SP)+, A1 ; Get the return address in A1 MOVE.L (SP)+, A0 ; and the handle in A0. _HGetState ; D0 <- Lock/Purge/Res bits BTST #Resource,D0 ; NE => itÕs indeed a rsrc BEQ.S @1 ; If not resource, just return, MOVE.L A0, -(SP) ; otherwise push the handle _WriteResource ; Attempt a write (ResChanged checked) @1 JMP (A1) ; and return to memory manager ;------ end of the resource mgr purge proc SetResPurge MOVE.L (SP)+, D0 ; Get return address in D0 TST.B (SP)+ ; Install or remove the hook? BNE.S @install ; install @clear ; clearing means leaving the font disk cache purge proc in place stb lea DiskCachePurgeProcedure,a1 ; the TrueType purge procedure stb BRA.S @continue @install ; installing. Put the resource mgr purge proc into the zoneÕs purgeProc lea RPHook,a1 ; stb @continue MOVE.L theZone,A0 ; Get the application zone <18apr85> BBMstb move.l a1,purgeProc(a0) ; Set or clear the purge hook stb MOVE.L D0, -(SP) ; Push return address back RsClrEx ; rts from SetResLoad, ResError & CurResFile <13aug85> BBM CLR.B ResOneDeep ; disable one deep calls <13aug85> BBM CLR.W RomMapInsert ; disable rom map next time <13aug85> BBM RTS ; and return. ;_______________________________________________________________________________ ; ; Routine: PROCEDURE SetResLoad(autoLoad: BOOLEAN); ; ; Arguments: 4(SP) (input.B) autoload flag ; ; Called By: A-trap through dispatcher ; Calls: NONE ; ; Function: Set automatic-loading true or false. If autoLoad=TRUE, then the ; resource manager will load resources from the disk if necessary. ; If FALSE, returns the handle, which may be empty. ;_______________________________________________________________________________ SetResLoad MOVE.L (SP)+,A0 ; Get return address MOVE.B (SP)+,ResLoad ; Set ResLoad from proc parameter MOVE.L A0,-(SP) ; Get return address <13aug85> BBM BRA.S RsClrEx ; and return <13aug85> BBM ;_______________________________________________________________________________ ; ; Routine: FUNCTION CurResFile: INTEGER; ; ; Arguments: 4(SP) (output.W) refnum of current resource file ; ; Called By: A-trap through dispatcher ; Calls: NONE ; ; Function: Returns the reference number of the current resource file. ;_______________________________________________________________________________ CurResFile MOVE.W CurMap, 4(SP) ; else Set the function result as current map <15jul85> BBM BRA.S RsClrEx ; and return <13aug85> BBM ;_______________________________________________________________________________ ; ; Routine: FUNCTION ResError: INTEGER; ; ; Arguments: 4(SP) (input.L) place to store ResError code ; 4(SP) (output.L) ResError code ; ; Called By: A-trap through dispatcher ; Calls: NONE ; ; Function: Return a resource error code. Usually the code will be an I/O ; error, but there are several resource-only errors which are ; reported through this call. ;_______________________________________________________________________________ ResError MOVE.W ResErr,4(SP) ; Set error code as function result BRA.S RsClrEx ; and return <13aug85> BBM ;_______________________________________________________________________________ ; ; Routine: PROCEEDURE AddReference(theResource: Handle; theID: INTEGER; ; name: Str255); ; ; Arguments: (output.W) ResError code ; ; Called By: A-trap through dispatcher ; Calls: RsClrEx ; ; Function: Return a resource error code of AddRefFailed. ;_______________________________________________________________________________ AddReference MOVE.L (SP)+,A0 ; get return address into A0 <17oct85> BBM ADDA.W #$A,SP ; strip ten bytes off stack (parameters) <17oct85> BBM MOVE.L A0,-(SP) ; push return address <17oct85> BBM MOVE.W #AddRefFailed,ResErr ; Set error code as failed <17oct85> BBM BRA.S RsClrEx ; and return <17oct85> BBM ;_______________________________________________________________________________ ; ; Routine: PROCEEDURE RmveReference(theResource: Handle); ; ; Arguments: (output.W) ResError code ; ; Called By: A-trap through dispatcher ; Calls: RsClrEx ; ; Function: Return a resource error code of AddRefFailed. ;_______________________________________________________________________________ RmveReference MOVE.L (SP)+,(SP) ; strip parameter with return address <17oct85> BBM MOVE.W #RmvRefFailed,ResErr ; Set error code as failed <17oct85> BBM BRA.S RsClrEx ; and return <17oct85> BBM ;_______________________________________________________________________________ ; ; Routine: FUNCTION GetResAttrs(theResource:Handle): INTEGER; ; ; Arguments: 8(A6) (input.L) handle to the resource ; (A0) (input.L) same as 8(A6) ; 12(A6) (output.W) resource attributes in low order byte ; ; Called By: A-trap through dispatcher ; Calls: StdEntry, RefHandle, StdFourExit ; ; Function: Given a resource, return the resource attributes in the low order ; byte of the integer result. If a reference to the resource exists ; in the current resFile, returns attributes of that reference. ;_______________________________________________________________________________ GetResAttrs BSR Std1Entry ; Link A6, save regs <22apr85> BBM MOVE.L (A0), A1 ; Get the resource handle BSR.S RefHandle ; Scan for reference or handle BMI.S @9 ; if not found, resErr set, just exit. MOVE.B RAttr(A2), 13(A6) ; Set function result in low byte of result @9 BRA StdFourExit ; and branch to standard exit ;_______________________________________________________________________________ ; ; Routine: PROCEDURE SetResAttrs(theResource: Handle; attrs: INTEGER); ; ; Arguments: 10(A6) (input.L) handle to the resource ; 8(A6) (input.W) new attributes ; ; Called By: A-trap through dispatcher ; Calls: StdEntry, RefHandle, StdSixExit ; ; Function: Given a resource, set the resource attributes which are in the low ; order byte of the integer parameter. These new attributes will only ; be in effect the next time the resource is loaded, except for SysHeap, ; which will be ignored. If a reference to the resource exists in the ; current resource file, the attributes of the reference will be set. ; <28jan85> BBM ram patches added in. ;_______________________________________________________________________________ SetResAttrs BSR Std1Entry ; Link A6, save regs <22apr85> BBM MOVE.L 10(A6), A1 ; Get the resource handle BSR.S RefHandle ; Look for a reference or the resource BMI.S @9 ; if not found, ResErr set, just exit. CMP.L RomMapHndl, A4 ; is it in the ROM map? <28mar85> BBM BEQ.S @9 ; then exit here too (just a nop) <28mar85> BBM MOVE.B 9(A6), RAttr(A2) ; Set attr byte in the location longword MOVE.L (A4),A0 ; Dereference map handle <28jan85> BBM BSET #MapChanged,MAttr(A0) ; Set the map changed bit BSR UpdateOverriddenChangedBits ; set the changed bit for any files that may be overridden by the map in A4 @9 BRA StdSixExit ; pop 6 bytes and exit ;_______________________________________________________________________________ ; ; Routine: RefHandle (utility) ; ; Arguments: A1 (input.L) handle to the resource. ; Ax (input.L) assumes regs setup as per StdEntry ; ; Called By: GetResAttrs, SetResAttrs, GetResInfo, SetResInfo ; Calls: HandleScan ; ; Function: Scans for reference, then handle. Returns MI if neither found, ; and sets ResErr to ResNotFound. ;_______________________________________________________________________________ RefHandle BSR HandleScan ; Otherwise find the resource itself BEQ.S @9 ; if resource found, exit, else MOVE.W #ResNotFound, ResErr ; Set ResErr, CC's @9 RTS ; ...and return ;_______________________________________________________________________________ ; ; Routine: PROCEDURE GetResInfo(theResource:Handle; VAR theID:INTEGER; ; VAR theType:LONGINT; VAR name:Str255); ; ; Arguments: 20(A6) (input.L) handle to res ; 16(A6) (input.W) Resource ID ; 12(A6) (input.L) Resource type ; 8(A6) (input.L) pointer to pascal string ; ; Called By: A-trap through dispatcher ; Calls: StdEntry, RefHandle, NameResource, CopyStr, StdExit ; ; Function: Given a resource, return the information about the resource in ; the VAR parameters. If a reference to the resource exists in the ; current resFile, the information will be returned about the ; reference. ;_______________________________________________________________________________ GetResInfo BSR Std1Entry ; Link A6, save regs <22apr85> BBM MOVE.L 20(A6),A1 ; Get the resource handle BSR.S RefHandle ; Look for a reference to this resource BEQ.S @1 ; If OK, go on, else ResErr set, LEA MinusOne,A2 ; point to -1, -1, MOVEQ #0, D3 ; and set type to null type. @1 LEA 16(A6),A0 ; Get top parameter address MOVE.L (A0),A1 ; Get address of the ID variable MOVE.L A1,D0 ; If pointer to var parameter is nil <06may85> BBM BEQ.S @2 ; ... then don't write out. MOVE.W RID(A2),(A1) ; Store it @2 MOVE.L -(A0),A1 ; Get address of the type variable MOVE.L A1,D0 ; If pointer to var parameter is nil <06may85> BBM BEQ.S @3 ; ... then don't write out. MOVE.L D3,(A1) ; Store it @3 MOVE.L -(A0),A1 ; Get address of the name variable MOVE.L A1,D0 ; If pointer to var parameter is nil <06may85> BBM BEQ.S @9 ; ... then don't write out. CLR.B (A1) ; Store first byte zero, for null string BSR NameResource ; Given RNameOff(A2), point A0 to the name. BMI.S @9 ; If can't find the name, no go BSR.S CopyStr ; Copy string in A0 to A1. @9 MOVEQ #16,D0 ; Pop off 16 bytes of parameter BRA StdExit ; and exit. ;_______________________________________________________________________________ ; ; Routine: CopyStr (utility) ; ; Arguments: A0 (input.L) pascal String pointer ; A1 (input.L) pointer to new location ; ; Called By: GetResInfo, AddName ; Calls: _BlockMove ; ; Function: Given a Pascal string in A0 and an address in A1, copies the ; string including the length byte to A1 using blockMove. ;_______________________________________________________________________________ CopyStr MOVEQ #0, D0 ; Zero high order bits. MOVE.B (A0), D0 ; Get length of string ADDQ.W #1, D0 ; include length byte. <14jun85> BBM _BlockMoveData ; Copy the string to A1 RTS ; and return. ;_______________________________________________________________________________ ; ; Routine: PROCEDURE SetResInfo(theResource:Handle; theID:INTEGER; ; theName:Str255); ; ; Arguments: 14(A6) (input.L) handle to the resource ; 12(A6) (input.W) resource ID ; 8(A6) (input.L) pointer to pascal string ; ; Called By: A-trap through dispatcher ; Calls: StdEntry, RefHandle, CheckGrow, RmveName, AddName, StdExit ; ; Function: Given a resource, Set the information about the resource. If the ; name pointer is NIL, doesn't change the name. If the protect bit ; is on, returns without doing anything. If a reference to the ; resource exists in the current resFile, the information about the ; reference will be set. ;_______________________________________________________________________________ SetResInfo BSR Std1Entry ; Link A6, save regs <22apr85> BBM MOVE.L 14(A6), A1 ; Get the resource handle BSR.S RefHandle ; Look for a reference to this resource BMI.S @9 ; Couldn't find it, or reference! BTST #ResProtected,RAttr(A2) ; Is it protected from being changed? BNE.S @5 ; Yes, return immediately, otherwise <16apr85> BBM MOVE.L 8(A6),D0 ; Check for a nil name pointer <22aug85> BBM BEQ.S @1 ; if no name just change RID SUB.L A1, A1 ; (no handle) BSR CheckGrow ; can the resfile + map grow? (sets ResErr) BMI.S @9 ; if failed, can't set. Bad boundary condition. MOVE.L D0, A0 ; Get name pointer in A0 BSR RmveName ; Remove old name, if it exists BSR AddName ; Add the new one back, Sets in RNameOff(A2) BSR SetRFEOF ; set new end of file <26aug85> BBM @1 MOVE.L (A4),A0 ; Dereference map handle <22aug85> BBM BSET #MapChanged,MAttr(A0) ; set the mapchanged bit BSR UpdateOverriddenChangedBits ; set the changed bit for any files that may be overridden by the map in A4 MOVE.W 12(A6), RID(A2) ; Get new ID and store it BRA.S @9 ; skip over error @5 MOVE.W #resAttrErr,ResErr ; ... else mark it as error <16apr85> BBM @9 MOVEQ #10, D0 ; pop off 10 bytes of parameters BRA StdExit ; Restore regs, unlink A6 ;_______________________________________________________________________________ ; ; Routine: PROCEDURE AddResource(theResource:Handle; theType:LONGINT; ; theID:INTEGER; name:Str255); ; ; Arguments: 18(A6) (input.L) handle to the resource ; 14(A6) (input.W) theType ; 12(A6) (input.W) theID ; 8(A6) (input.L) pointer to pascal string ; ; Called By: A-trap through dispatcher ; Calls: StdEntry, HandleScan, GetCurMap, CheckGrow, AddNewRef, AddName, ; AllocRes, StdExit ; ; Function: Add a reference to the given resource in the current map. Set ID ; and name in the reference. Mark the resource to be written out ; into the correct resource map data section. ;_______________________________________________________________________________ AddResource move.l ExpandMem,a0 ; move.b ExpandMemRec.emScanOverrideMaps(a0),D0 ; save override state. (StdZEntry must preserve d0) clr.b ExpandMemRec.emScanOverrideMaps(a0) ; turn it off for StdEntry BSR StdZEntry ; Link A6, save regs <12aug85> BBM bsr FlushResourceCache ; need to flush the resource cache move.l ExpandMem,a0 ; move.b d0,ExpandMemRec.emScanOverrideMaps(a0) ; restore override state MOVE.W #AddResFailed,ResErr ; Assume error. CheckGrow resets ResErr. MOVE.L 18(A6), A1 ; Get handle in A1 MOVE.L A1, D0 ; Set CC's BEQ.S @9 ; if NIL handle, can't add! BSR HandleScan ; Is the data already a resource? BEQ.S @9 ; cann't add another <21may85> BBM BSR GetCurMap ; Get the current map for diskFull check BSR CheckGrow ; Room for resource + map overhead? ; CheckGrow calls ResRW which tests MapReadOnly <28mar85> BBM BMI.S @9 ; if not, can't add the resource. ; Return with error from CheckGrow. ; If successful, ResErr := 0. MOVE.L 14(A6), D3 ; Put type of resource to add in D3 BSR.S AddNewRef ; Set up a new reference to the resource ; Returns A2-->reference location. MOVE.W 12(A6),(A2)+ ; Set ID of reference MOVE.W #-1,(A2)+ ; Assume no name yet MOVE.L #$02000000,(A2)+ ; ResChanged set MOVE.L 18(A6), A0 ; Get the handle _HSetRBit ; Mark it like a gentleman MOVE.L A0, (A2) ; Finally, set handle. SUBQ.L #8, A2 ; Back up for AddName, AllocRes. MOVE.L 8(A6), A0 ; Get pointer to reference name BSR AddName ; Name set in RNameOff(A2). ; A2, A3 preserved + correct. BSR AllocRes ; Allocate new resource loc'n. bsr FlushChangedFONDs ; flush 'FOND' candidate list if this is a FOND stb @9 MOVEQ #14, D0 ; Pop off 14 bytes of parameter BRA StdExit ; Restore regs, unlink A6 ;_______________________________________________________________________________ ; ; Routine: AddNewRef (utility) ; ; Arguments: A4 (input.L) handle to map ; A3 (input.L) pointer into map ; D3 (input.L type of resource to add ; A2 (output.L) pointer to loc of new reference ; ; Called By: AddResource ; Calls: TypeScan, TypeScanAll, ShiftBlock, MoveNames, GetTypes, ; SkipToEntry ; ; Function: add a new reference in the map (of type specified in D3) ;_______________________________________________________________________________ AddNewRef BSET #MapChanged, MAttr(A3) ; Set mapChanged bit BSR UpdateOverriddenChangedBits ; set the changed bit for any files that may be overridden by the map in A4 AddNewRefWithoutUpdate ; EntryPoint for MakeOverrideMap that doesn't set mapChanged bit. kc BSR TypeScan ; Scan for type of referent (D3) in cur map BEQ.S @2 ; If found, type exists, otherwise ; Add both a new type and a new entry. MOVEQ #RESize+TSize, D0 ; Move names up by RE+TE size to leave BSR MoveNames ; room in handle for type and res entry. BSR GetTypes ; Point to first type, if any. BMI.S @1 ; If none, skip SkipToentry (adding 1st one!) BSR SkipToEntry ; ... skip to res entry. A2-->first res entry. @1 ; start adding type here (A2 should point at loc where to add new type) MOVE.L A2, A3 ; A3 is location of new type entry. MOVE.L (A4), A2 ; Dereference map handle. ADD.W MNames(A2), A2 ; A2 points to new res entry loc'n. SUB.W #RESize+TSize, A2 ; (name block already moved.) MOVEQ #TSize, D0 ; Now shift all entries up by TSize MOVE.L A3, A0 ; (A3=first entry loc) MOVE.L A2, A1 ; new res entry locn is high bounds of block. BSR ShiftBlock ; Made room for type entry now. MOVE.L (A4), A0 ; Dereference map handle ADD.W MTypes(A0), A0 ; Point to type block ADDQ.W #1, (A0) ; Increment type count. MOVE.L D3, (A3)+ ; Set the new type CLR.W (A3)+ ; Set TCount to 0 (1 entry) SUB.L A0, A1 ; Subtract first entry loc from block start MOVE.W A1, (A3) ; to get the offset (new entry needs +TSize too). ADDQ.L #TSize, A2 ; add offset to returned loc'n MOVE.W (A0)+, D5 ; Get number of types BRA.S UTOffsets ; update ALL type offsets by TSize and exit. ; The type already exists. Just add a new entry. ; This part only adds the new entry @2 MOVEQ #RESize, D0 ; Move names up by entry size only. BSR MoveNames ; Move names up for room MOVE.L (A4), A1 ; Dereference map handle. ADD.W MNames(A1), A1 ; end of block to move is beginning of names. SUB.W D0, A1 ; names moved already--skip back to old val. BSR TypeScan ; Scan for type of referent (D3) in cur map MOVE.L A2, -(SP) ; Save type entry location for offset updating ADDQ.W #1,TCount(A2) ; Increment entry count for this type MOVEQ #RESize,D0 ; get offset to last Rsrc entry in D0 <14sep85> BBM MULU TCount(A2),D0 ; D0 has offset past the first entry <14sep85> BBM MOVE.W TOffset(A2),A2 ; Skip to the first entry of that type ADD.L A3,A2 ; add in block address gives absolute addr. ADD.W D0,A2 ; point to the last entry <14sep85> BBM MOVE.L A2,A0 ; Start moving entries from here to names. MOVEQ #RESize,D0 ; Move entries up by entry size only. BSR ShiftBlock ; shift block up by RESize. MOVE.L (SP)+, A0 ; Restore type entry location, and update ; following types by RESize. BRA.S UTInLoop ; jump in lp to skip type entry ;_______________________________________________________________________________ ; ; Routine: UTOffsets, UTInLoop (utilities) ; ; Arguments: D0 (input.W) Delta offset for this type ; D5 (input.L) types-1 remaining ; A0 (input.L) points to first entry ; ; Called By: (UTOffsets): AddNewRef, RmveCmn ; (UTInLoop): AddNewRef ; Calls: NONE ; ; Function: Update type offsets ;_______________________________________________________________________________ UTOffsets ADD.W D0, TOffset(A0) ; Increment by D0 UTInLoop ADDQ.W #TSize, A0 ; bump address DBRA D5, UTOffsets ; Update each name offset RTS ;_______________________________________________________________________________ ; ; Routine: PROCEDURE RmveResource(theResource: Handle); ; RmveCmn (utility) ; ; Arguments: 8(A6) (input.L) handle to the resource ; (A0) (input.L) handle to the resource ; ; Called By: (RmveResource): A-trap through dispatcher ; (RmveCmn): RmveResource (by falling through) ; Calls: (RmveResource): StdEntry, HandleScan, RmveExit ; (RmveCmn): RmveName, TypeScan, TypeScanALl, ShiftBlock, UTOffsets, ; MoveNames, StdFourExit ; ; Function: Remove a resource from the map, and from the data section of the ; resource file when UpdateResFile/CloseResFile is called. May ; only be removed if it is in current map and is not protected. ;_______________________________________________________________________________ RmveResource BSR Std1Entry ; Link A6, save regs <22apr85> BBM bsr FlushResourceCache ; preserves a0 MOVE.L (A0), A1 ; Get the handle in A1 BSR HandleScan ; Find the handle, wherever it is. BMI RmveErr ; Can't find it, so can't remove it. CSS bsr FlushChangedFONDs ; flush 'FOND' candidate list if this is a FOND stb BTST #ResProtected, RAttr(A2); Is it protected? BNE RmveErr ; Yes, return immediately CSS ; RmveResource is documented to only allow you to remove a resource ; when it's homeresfile is in CurMap. With overrides we want to modify ; this behavior slightly to allow RmveResource calls from CurMap ; and any files that are overridden by CurMap. CMP.W CurMap, D6 ; Is it in the current map? BEQ.S RmveIt ; If so, go ahead and remove itÉ subq #4,sp move.l a4,-(sp) _GetOverrideMap ; Get the override map for the map we found the resource in. MOVEA.L (sp)+,A3 ; Hold the override map in a3 the link we're looking for move.w CurMap,d1 ; Get CurMap move.l (a3),a3 ; Get Override map ptr in a3 cmp.w mRefNum(a3),d1 ; were we removing from an overridden file? beq.s RmveIt ; It wasn't an overridden file so we should check for "two deep bit" and other ; system files if the current map is the override of the system map. ; CSS changed to look at the override map to the system not SysMap! subq #4,sp move.l SysMapHndl,-(sp) _GetOverrideMap ; Get the override map for the system movea.l (sp)+,a3 ; hold the override map in a3 of the system move.w CurMap,d1 ; Get CurMap move.l (a3),a3 ; get override ptr in a3 cmp.w mRefNum(a3),d1 ; is the system override map the curmap? bne RmveErr ; no - bail out subq #2,sp move.l a4,-(sp) _IsThisASystemResourceMap ; See if this map is a font file or other two deep bit fileÉ tst.b (sp)+ beq.s RmveErr ; error outÉ CSS RmveIt MOVEA.L A1,A0 ; Mark it no longer a rsrc _HClrRBit ; MOVEQ #MCCMask, D0 ; MapChanged+MapCompact to be set in RmveCMn BSR UpdateOverriddenChangedBits ; set the changed bit for any files that may be overridden by the map in A4 ; Common code for remove reference/remove resource. ; A2 points to the resource entry. RmveCmn CLR.L HSCHandle ; invalidate cache always <18jul85> BBM MOVE.L (A4), A0 ; OR.B D0, MAttr(A0) ; Set mapChanged and possibly mapCompact. BSR RmveName ; Remove RNameOff(A2)'s name, if any. MOVEQ #-RESize, D7 ; Get -(resource entry size) MOVE.L A2, A0 ; Remember address of SUB D7, A0 ; NEXT entry, in A0. BSR TypeScan ; Scan for type of referent (D3) in cur map MOVE.L (A4), A1 ; Dereference map handle ADDA.W MNames(A1), A1 ; A1 points to the name block MOVE.L D7, D0 ; Copy (-RESize) in D0 BSR ShiftBlock ; Shift the block down MOVE.L A2, A0 ; Copy type entry address to A0 ADDQ #TSize, A0 ; Skip to next type entry SUBQ #1, D5 ; Decrement number of types BMI.S @1 ; If this is last type, go on, else BSR.S UTOffsets ; update following type offsets. @1 SUBQ.W #1, TCount(A2) ; decrement resource count for this type BPL.S @9 ; If still more resources of this type, quit ; If this was the last resource of the type, remove the type entry. ADDQ #TSize, A2 ; Skip to next type entry MOVE.L A2, A0 ; Moving next type over current, to delete. ADD D0, A1 ; move down name address by resource entry size MOVEQ #-TSize, D0 ; Shift this block down by type entry size ADD.L D0, D7 ; Decrement down TSize more, for names. BSR ShiftBlock MOVE.L (A4), A0 ; Dereference map handle ADDA.W MTypes(A0), A0 ; A2 points to the type block SUBQ #1, (A0) ; Decrement number of types MOVE.W (A0)+, D5 ; Get number of types in D5 BMI.S @9 ; No types left! just return BSR UTOffsets ; Update all type offsets by TSize. @9 MOVE.L D7, D0 ; Get accumulated shuffle in D0. BSR.S MoveNames ; Move names down 12 or 20 CMP.W #1,D6 ; IS THIS THE ROM MAP?? <04nov85> BBM BEQ.S @5 ; CC=EQ means ROM map (don't do SetEOF) <04nov85> BBM BSR SetRFEOF ; set new EOF <26aug85> BBM @5 CLR.W ResErr ; Remove succeeded! <04nov85> BBM RmveExit CLR.L HSCHandle ; Invalidate cache <12mar85> BBM BRA StdFourExit ; CSS added RmveErr label so that we don't have to keep loading ResErr RmveErr MOVE.W #RmvResFailed,ResErr ; indicate error doing remove BRA.S RmveExit ; and exit ;_______________________________________________________________________________ ; ; Routine: AddName (utility) ; ; Arguments: A0 (input.L) pointer to a name ; A2 (input.L) pointer to a resource entry ; ; Called By: SetResInfo, AddResource ; Calls: ResizeMap, CopyStr ; ; Function: Sets RNameOff(A2) to a name offset, and copies the name to the ; map block. ;_______________________________________________________________________________ AddName CLR.L HSCHandle ; invalidate cache always <18jul85> BBM MOVEM.L D0-D2/A0-A1, -(SP) ; save regs used (returning D2), and MOVEQ #-1, D2 ; Assume no string MOVE.L A0,D0 ; is the ptr nil? <13> stb BEQ.S @9 ; if so, return -1 for RNameOff TST.B (A0) ; is it empty? BEQ.S @9 ; if so, return -1 for RNameOff. MOVE.L (A4), A1 ; Dereference map handle MOVE.L MapSize(A1), D1 ; Copy current map size to D1. MOVE.L D1, D2 ; and to D2. MOVEQ #0, D0 ; Zero D0 MOVE.B (A0), D0 ; Get string length ADDQ.L #1, D0 ; Add 1 for len byte BSR.S ResizeMap ; Grow the map by string size. MOVEQ #0,D0 ; use all of D0 <06may85> BBM MOVE.L (A4), A1 ; Get map ptr again MOVE.W MNames(A1), D0 ; D0=offset to name block SUB.L D0, D2 ; mapSize-nameBlkoff := off to newname <06may85> BBM ADD.L D1, A1 ; Add endOfMap to get end address in A1 BSR CopyStr ; Copy the string in! @9 MOVE.W D2, RNameOff(A2) ; Set name offset in the entry MOVEM.L (SP)+, D0-D2/A0-A1 ; Restore regs RTS ; and exit. ;_______________________________________________________________________________ ; ; Routine: MoveNames (utility) ; ; Arguments: D0 (input.L) byte count ; A2 (input.L) pointer to map (see note below) ; A3 (input.L) pointer into map (see note below) ; A4 (input.L) handle to the map ; ; Called By: AddNewRef, RmveCmn ; Calls: ResizeMap, ShiftBlock ; ; Function: Moves the names up or down by the amount specified in D0. ; Resizes map each time. ; ; note: Adjusts A3, A2 to compensate for any block moving. ;_______________________________________________________________________________ MoveNames MOVEM.L D0-D1/D7/A0-A1, -(SP) ; Save regs MOVE.L (A4), A0 MOVE.L MapSize(A0), D1 ; Save original map size in D1 TST.L D0 ; Are we shrinking or growing? BMI.S @1 ; if Shrinking, resize after move BSR.S ResizeMap ; Otherwise grow first MOVE.L (A4), A0 ; Dereference handle (may have moved) @1 MOVE.L A0,A1 ; Copy address MOVEQ #0,D7 ; Get MNames(A0) into D7 with high word = 0 <06may85> BBM MOVE.W MNames(A0),D7 ; get offset to names ADDA.L D7,A0 ; and add offset to pointer. ADD.W D0,MNames(A1) ; (Update name block offset now) ADD.L D1,A1 ; Point A1 to original end of map BSR.S ShiftBlock ; Shift (A0..A1) up or down by D0 TST.L D0 ; Did we shrink or grow? BPL.S @9 ; Grew, map already resized, otherwise BSR.S ResizeMap ; Shrink it now @9 MOVEM.L (SP)+, D0-D1/D7/A0-A1 ; Restore regs RTS ; ...and return ;_______________________________________________________________________________ ; ; Routine: ResizeMap (utility) ; ; Arguments: D0 (input.L) delta byte count ; A2 (input.L) pointer to map (see note below) ; A3 (input.L) pointer into map (see note below) ; A4 (input.L) handle to the map ; ; ; Called By: MoveNames, AddName, RmveName ; Calls: _SetHandleSize, SetRFEOF ; ; Function: Given a byte count in D0, grows or shrinks the map. The map may ; move when growing, though not when shrinking. Calls SetRFEOF to ; set resource file EOF (reserving space). ; ; note: Adjusts A3, A2 to compensate for any block moving. ;_______________________________________________________________________________ ResizeMap BSR SaveRegs ; Saves A1/A0/D1/D0 and makes A2/A3 offsets <22aug85> BBM MOVE.L (A4), A0 ; Dereference handle ADD.L MapSize(A0), D0 ; Add delta to current size for new size_ MOVE.L D0, MapSize(A0) ; Set new mapSize. MOVE.L A4, A0 ; Get handle in A0 _SetHandleSize ; Set the new size (error handled in CheckGrow) BRA RestRegs ; Set EOF and exit through SetEOF2 <26aug85> BBM ;_______________________________________________________________________________ ; ; Routine: ShiftBlock (utility) ; ; Arguments: D0 (input.L) delta byte count ; A0 (input.L) low pointer to block to move ; A1 (input.L) high pointer to block to move ; ; Called By: AddNewRef, RmveCmn, MoveNames, RmveName ; Calls: _BlockMove ; ; Function: Given a delta (in bytes) in D0, shifts the block (A0..A1) up or ; down by D0. ;_______________________________________________________________________________ ShiftBlock MOVEM.L A0-A1/D0, -(SP) ; Save regs EXG D0, A1 ; D0=bytes to move, A1=delta SUB.L A0, D0 ; Subtract low from high to give size AND.L Lo3Bytes,D0 ; AND off high 8 bits ADD.L A0, A1 ; Add low to bytes to move, giving dest. _BlockMove ; Move the bytes MOVEM.L (SP)+, A0-A1/D0 ; Restore regs RTS ; ...and return ;_______________________________________________________________________________ ; ; Routine: NameUsedByOthers (utility) <11> stb ; ; Arguments: D0 (input.L) offset to name in name list ; A2 (input.L) resource entry of interest ; ; Called By: RmveName ; Calls: ; ; Function: Given an offset to a name in the namelist, return non-zero if ; any resource other than the resource of interest uses the same name ; offset. While this shouldnÕt ever be the case, such files do exist, ; and weÕll make them work. ;_______________________________________________________________________________ NameUsedByOthers MOVEM.L D3-D5/A2-A3,-(SP) ; Save rest of registers. ; MOVE.L A2,A3 ; A3 is now the resource of interest MOVE.L A2,-(SP) ; Save A2 BSR GetRsrcCnt ; Check all entries and update name offsets. ; A2 now points to the first rsrc entry ; D4 has the number of entries MOVE.L (SP)+,A3 ; A3 is now the resource of interest @loop CMP.L A2,A3 ; current resource vs. resource of interest BEQ.S @NextEntry ; skip this one, we already know it uses the name CMP.W RNameOff(A2),D0 ; is this name offset = the one of interest? BEQ.S @NameInUse ; yes? return non-zero @NextEntry ADD.W #RESize,A2 ; point to the next entry DBRA D4,@loop ; if there are more entries loop back MOVEQ #0,D0 ; zero indicates not in use BRA.S @done @NameInUse MOVEQ #1,D0 ; non-zero indicates in-use @done MOVEM.L (SP)+,D3-D5/A2-A3 ; Restore inner regs. RTS ; ...and return ;_______________________________________________________________________________ ; ; Routine: RmveName (utility) ; ; Arguments: A2 (input.L) pointer to resource entry ; A3 (input.L) pointer into map ; A4 (input.L) handle to map ; ; Called By: SetResInfo, RmveCmn ; Calls: ShiftBlock, ResizeMap, GetEntries ; ; Function: Given A2 pointing to a resource entry, removes the name pointed ; to by RNameOff(A2). Removing reference names requires that A2 ; point to RefID instead of RID. ;_______________________________________________________________________________ RmveName MOVEM.L D0-D2/A0-A1,-(SP) ; Save working regs MOVE.W RNameOff(A2),D2 ; Copy name offset to D2. BMI.S @9 ; if not a real offset, just exit. MOVE.L D2,D0 ; offset into namelist <11> stb BSR.S NameUsedByOthers ; Is anyone else is using this instance of the name? <11> BNE.S @9 ; ItÕs in use. DonÕt remove the name <11> MOVE.L (A4),A0 ; Dereference map handle MOVE.L A0,A1 ; Copy ptr to A1 MOVEQ #0,D0 ; Get name offset (upto 64k) <06may85> BBM MOVE.W MNames(A0),D0 ; ... and stuff into low word ADD.L D0,A0 ; A0 points to the name block ADD.W D2,A0 ; and finally the string itself. ADDA.L MapSize(A1),A1 ; A1 points to the end of the map. MOVEQ #0, D0 ; Zero high order MOVE.B (A0), D0 ; Get length byte ADDQ.L #1, D0 ; Add 1 to include the length byte ADD.L D0, A0 ; point A0 to the NEXT string NEG.L D0 ; Negate, since shrinking MOVE.L D0, D1 ; Copy delta to D1 for updating offsets. BSR.S ShiftBlock ; Shift the block (A0..A1) down strSize. BSR.S ResizeMap ; and shrink the map. A2-A3 corrected. MOVEM.L D3-D5/A2-A3,-(SP) ; Save rest of registers. <24aug85> BBM BSR GetRsrcCnt ; Check all entries and update name offsets. <24aug85> BBM @1 CMP.W RNameOff(A2),D2 ; is this name offset < the removed one? <24aug85> BBM BGE.S @2 ; if so, skip it, else ADD.W D1,RNameOff(A2) ; Offset shrinks by D1. @2 ADD.W #RESize,A2 ; point to the next entry DBRA D4,@1 ; if there are more entries loop back <24aug85> BBM MOVEM.L (SP)+,D3-D5/A2-A3 ; Restore inner regs. <24aug85> BBM @9 MOVEM.L (SP)+, D0-D2/A0-A1 ; Restore outer regs MOVE.W MinusOne, RNameOff(A2) ; Set name offset to -1. RTS ; and return. ;_______________________________________________________________________________ ; ; Routine: FUNCTION SizeResource(theResource: Handle): LONGINT; ; ; Arguments: 8(A6) (input.L) resource handle ; A0 (input.L) resource handle ; 12(A6) (output.L) resource size ; ; Called By: A-trap through dispatcher ; Calls: StdResEntry, _GetHandleSize, SizeRsrc, StdFourExit ; ; Function: Return the size of the resource pointed at by . If ; no resource was found for , return (-1). ; note: ; <22Jan85> BBM This was first includeded in the Ram System in 1984. It was not ; put in ROM 7.0. This routine will return the size of a resource. ;_______________________________________________________________________________ SizeResource BSR Std2ResEntry ; Link A6, save regs <21aug85> BBM TST.L (A1) ; has it been purged? BEQ.S @0 ; if so, read size from file MOVE.L A1,A0 ; Resource is already in memory. _GetHandleSize ; (handle to resource is in A0) BRA.S SizeRExit ; EXIT @0 MOVE.B RAttr(A2),-(SP) ; Rsrc not in memory, save state of ... BSR SizeRsrcDecomp ; attributes. Figure out the size on disk after decompression. kc MOVE.B (SP)+,RAttr(A2) ; restore attributes state. SizeRExit ; added common exit for MaxsizeRsrc <21aug85> BBM MOVE.L D0,12(A6) ; Return the result and ... BRA StdFourExit ; Pop 4 bytes and standard exit ;_______________________________________________________________________________ ; ; Routine: FUNCTION MaxSizeRsrc(theResource: Handle): LONGINT; ; ; Arguments: 8(A6) (input.L) resource handle ; A0 (input.L) resource handle ; 12(A6) (output.L) resource size ; ; Called By: A-trap through dispatcher ; Calls: StdResEntry, SpaceAt, _GetHandleSize, SizeRExit ; ; Function: Return the maximum size of the given resource. Note ; no resource was found for , return (-1). ;_______________________________________________________________________________ MaxSizeRsrc ; <02may85> BBM BSR Std2ResEntry ; Link A6, save regs <21aug85> BBM TST.L (A1) ; has it been purged? BNE.S @0 ; if CC=EQ, read size from Map BSR SpaceAt ; Get the Size available <13aug85> BBM BRA.S @9 ; EXIT @0 MOVE.L A1,A0 ; Resource is already in memory. _GetHandleSize ; (handle to resource is in A0) @9 BRA.S SizeRExit ; write out result and exit <21aug85> BBM ;_______________________________________________________________________________ ; ; Routine: FUNCTION RsrcMapEntry(theResource: Handle): LONGINT; ; ; Arguments: 8(A6) (input.L) resource handle ; A0 (input.L) resource handle ; 12(A6) (output.L) resource entry offset ; ; Called By: A-trap through dispatcher ; Calls: StdResEntry, SizeRExit ; ; Function: Return the offset in the map to the resource entry. ;_______________________________________________________________________________ RsrcMapEntry ; <21aug85> BBM BSR Std2ResEntry ; Link A6, save regs MOVE.L A2,D0 ; Get pointer to rsrc entry SUB.L (A4),D0 ; sub pointer to beginning of map _StripAddress ; get rid of any masterpointer bits @9 BRA.S SizeRExit ; write out result and exit <21aug85> BBM ;_______________________________________________________________________________ ; ; Routine: FUNCTION rGetResource(theType: ResType; theID: INTEGER): Handle; ; ; Arguments: 10(A6) (input.L) resource type ; 8(A6),A0(input.W) resource ID ; 14(A6) (output.L) resource handle ; ; Called By: A-trap through dispatcher ; Calls: GetResource ; ; Function: do a normal GetResource without the rom map; if that fails, ; do GetResource with the rom map inserted. ; ; NOTE: _GetResource expects a specific items on the stack when called. ; This routine depends heavily on that stack. Below is a picture ; of the stack just before the _GetResource trap is executed ; (starting in the middle of the stack and ending at the top of stack, ; or starting in high memory and decending down in memory). ; ; handle 4 bytes ; type 4 bytes (E bytes back on stack after < subq #4,sp >) ; ID 2 bytes (C bytes back on stack after < subq #4,sp >) ; rtn addr 4 bytes (8 bytes back on stack after < subq #4,sp >) ; rtn addr 4 bytes (4 bytes back on stack after < subq #4,sp >) ; handle 4 bytes (0 bytes back on stack after < subq #4,sp >) ; type 4 bytes ; ID 2 bytes ;_______________________________________________________________________________ ;„„„ Do not roll in patch from system file into this routine „„„ grStFr equ $0E ; size of the stack frame. (see note above) rGetResource clr.b ROMMapInsert ; make sure we donÕt use rom map bsr.s @getrsrc ; bne.s @exit ; if handle is not zero, then we donÕt check rom st.b ROMMapInsert ; else make sure we use rom map bsr.s @getrsrc ; @exit ; std exit to strip the stack move.l (sp)+,a0 ; strip off the return address into a0 addq #6,sp ; strip off type and ID jmp (a0) ; and return through a0 @getrsrc ; go do GetResource move.b resload,ROMMapInsert+1 ; set temp value of resload to current resload subq #4,sp ; save room for another handle (see note above) move.l grStFr(sp),-(sp) ; push type again move.w grStFr+2(sp),-(sp) ; push ID again _GetResource ; move.l (sp)+,grStFr(sp) ; push the handle we got back into the area ; the user saved for the handle and set ccÕs rts ; ;=== HereÕs some new stuff as of 3/11/92 ================================================ ;_______________________________________________________________________________ ; CacheResource builds the list of resources that are actually counted or indexed. Calls ; to _AddResource and _RmveResource will flush this cache. The cache contents look like ; this: ; ; Offset Contents ; 0 Cache flags ; 2 File reference number ; 4 Resource type in cache ; 8 Number of entries in cache - 1 ; 12 Beginning of cache information ; 0 Handle to resource map containing this resource <31> ; 4 Offset from beginning of map to this resource (word) <31> ; 6 ID of this resource (word) <29> ; ; The cache flags word is a bit field describing the state of the Resource Manager ; when the cache was formed. The cache will be flushed if the current state of the ; Resource Manager does not match the state when the cache was formed. The following ; bits are currently defined for the cache flags: ; ; (0) kCacheIsOneDeepBit Cache was formed on a _Count1Resources or _Get1IxResource call. ; (1) kCacheHasROMResourcesBit Cache was formed when ROMMapInsert was true. ; (2) kCacheHasOverridesBit Cache was formed when emScanOverrideMaps was true. ; CacheResource move.l (sp)+,a0 ; Get return address move.l (sp)+,d0 ; Get resource type move.l a0,-(sp) ; Restore return address movem.l d2-d7/a1-a4,-(sp) ; Save registers move.l d0,d7 ; Keep type in a nonvolatile place move.l ExpandMem,a0 move.b ExpandMemRec.emScanOverrideMaps(a0),d3 ; <35> Get scan override state bz.s @overridingNotOn ; <35> Why would anyone want to do this? move.w #kCacheHasOverridesMask,d3 ; <35> Set to a known value, since Pascal would have put a 1 in emScanOverrideMaps, whereas C would have put in -1, and who knows what Asm would have doneÉ @overridingNotOn move.l ExpandMemRec.emResourceCache(a0),d0 ; Get cached resource from expanded low mem beq.s @setupCache ; Cache doesnÕt exist. Go build it move.l d0,a0 ; ; <7> See if the deepness of the cache matches that of ResOneDeep. If not, force the ; cache to be rebuilt. ; <34> Also make sure that ROMMapInsert hasnÕt changed since the cache was formed. ; move.l (a0),a0 move.b ResOneDeep,d1 ; Get one deep setting of current call andi.w #kCacheIsOneDeepMask,d1 ; Just keep the low bit move.b ROMMapInsert,d2 ; <34> Check ROMness of cache too andi.w #kCacheHasROMResourcesMask,d2 ; <34> Just get a bit so we can compare against the cache flags or.w d1,d2 ; <34> Merge deepness and ROMness or.w d3,d2 ; <35> Merge overrideness in with the other two cmp.w (a0)+,d2 ; Does the deepness of the cache match ResOneDeep? bne.s @deepnessDoesntMatch ; Yes. btst #kCacheIsOneDeepBit,d2 ; <11> <23> Check the deepness of the current call bz.s @mapMatches ; <11> If the call is not one deep, go ahead and use the cache move.w CurMap,d1 ; <10> cmp.w (a0)+,d1 ; <10> One deep from same map? beq.s @mapMatches ; <10> Yes move.w d1,-2(a0) ; <11> CurMap has changed. Remember the new one for next time @deepnessDoesntMatch clr.l (a0) ; Nail type to force cache to rebuild @mapMatches move.l d0,a0 ; Get handle _GetHandleSize sub.l #kCacheHeaderSize,d0 ; DonÕt count header information asr.l #3,d0 ; <31> Figure out how many things can fit in the existing handle move.l d0,d6 ; Save this count move.l a0,a3 move.l (a3),a0 move.w d2,(a0)+ ; <34> Save deepness, ROMness, and overrideness in cache flags move.w CurMap,(a0)+ ; <11> Save CurMap for one deep calls cmp.l (a0),d7 ; Does the cached type match the one requested? beq @exitCacheResource ; If so, exit move.l d7,(a0)+ ; Use existing handle for cache addq #4,a0 ; Point to first entry bra.s @buildCache ; ; Allocate a new handle for the resource cache ; @setupCache move.l #(kInitialEntryCount * kCacheEntrySize) + kCacheHeaderSize,d0 ; Space for header and kInitialEntryCount entries. <29> _NewHandle ,Sys,Clear ; Get the handle bne @exitCacheResource move.l a0,a3 ; Remember the handle move.l ExpandMem,a0 move.l a3,ExpandMemRec.emResourceCache(a0) ; Save it in expand mem move.l (a3),a0 move.b ResOneDeep,d0 andi.w #kCacheIsOneDeepMask,d0 move.b ROMMapInsert,d1 ; <34> Remember ROMMapInsert in flags andi.w #kCacheHasROMResourcesMask,d1 ; <34> or.w d1,d0 ; <34> Merge the two attributes or.w d3,d0 ; <35> Merge in override setting move.w d0,(a0)+ ; Save deepness in cache flags move.w CurMap,(a0)+ ; <11> Save CurMap for one deep calls move.l d7,(a0)+ ; Save the resource type to cache addq #4,a0 ; Point to first index moveq #kInitialEntryCount,d6 ; Number of entries left before more room is needed ; ; A0 now points to the address to begin saving resource information, and D6 contains ; a zero based count of how many cache entries are still available before the handle ; needs to be grown. A3 contains the cache handle. ; ; Get current map to start walking the resource chainÉ @buildCache movem.l a2-a4/d1-d2/d6,-(sp) ; save registers trashed by GetCurMap BSR GetTopMap ; get the current maphndl in a4 move.l a4,d0 ; keep it in d0 movem.l (sp)+,a2-a4/d1-d2/d6 ; save registers trashed by GetCurMap moveq #0,d5 ; Count of entries placed in the cache so far @buildLoop move.l d0,a4 move.l (a4),a1 ; Dereference map handle add.w mTypes(a1),a1 ; Get to type list move.l a1,a2 ; Copy top of block move.w (a2)+,d4 ; Get number of types in this map bmi @cacheNextMap ; If no resources in this map, go on to next map CSS ; ; Find the type in D7 in the resource map. ; @typeSearch cmp.l TType(a2),d7 ; Is this the right type? beq.s @foundTypeEntry ; Yes, go on addq #TSize,a2 ; Otherwise, check next type dbra d4,@typeSearch bra @cacheNextMap ; If we fall through, no resources of this type in this map CSS ; ; Got the type. Now determine whether or not to cache each one. ; @foundTypeEntry move.w tCount(a2),d4 ; Number of resources of this type moveq #0,d2 move.w tOffset(a2),d2 ; Remember offset for cache add.l d2,a1 ; Get to reference list from type list move.l a1,a2 ; Keep reference pointer in A2 move.l ExpandMem,a1 ; <36> If emScanOverrideMaps is false, then treat override maps tst.b ExpandMemRec.emScanOverrideMaps(a1) ; <36> as normal resource maps, and always include the overridden resources for counting and indexing bz.s @addToCache ; <36> move.l (a4),a1 ; Point to the resource map btst #dontCountOrIndexDuplicatesBit,mInMemoryAttr(a1) ; Is our magic bit set? sne d3 ; Use D3 to flag whether this bit was set @addToCacheLoop tst.b d3 ; Check to see if this entry is a duplicate? beq.s @addToCache ; If not, add the resource blindly ; ; dontCountOrIndexDuplicatesBit is set. Determine whether this entry matches the ID ; of a previous resource in the cache. ; bsr IsDuplicate ; See if this ID was already used bne.s @dontAddToCache ; If it is, donÕt add it to the cache. ; ; Add this resource to the cache. Remember the file reference number of the map it ; came from, and its ID. ; @addToCache subq #1,d6 ; Adding another entry bge.s @doAdd ; If thereÕs still space left in the cache, add the entry ; ; Out of space in the cache. Double itÕs size. ; move.l (a3),a1 sub.l a1,a0 ; Compute current byte offset into cache exg a3,a0 ; Get handle _GetHandleSize sub.l #kCacheHeaderSize,d0 ; DonÕt count header info for size calculations move.l d0,d6 ; Need to recalc number of available entries in a sec asl.l #1,d0 ; Double the size of the cache add.l #kCacheHeaderSize,d0 ; And some space for the header _SetHandleSize ; Set the new size bne.s @exitCacheResource asr.l #3,d6 ; <31> Divide by 8 to get count from size subq #1,d6 ; One entry will be used up right away. move.l (a0),a1 ; Get pointer in case it moved add.l a1,a3 ; Add pointer to offset thatÕs saved in A3 exg a3,a0 ; And swap the handle and the pointer @doAdd addq #1,d5 ; Increment the count move.l a4,(a0)+ ; <31> Remember the map handle move.w d2,(a0)+ ; Remember offset to resource move.w rID(a2),(a0)+ ; <29> Remember ID of this resource @dontAddToCache add.w #RESize,a2 ; Point to next entry add.w #RESize,d2 ; Update offset to next resource dbra d4,@addToCacheLoop @cacheNextMap TST.B ResOneDeep ; if one deep set, don't get next map <26jun85> BBM BEQ.S @notOneDeepMap ; ... else do normal stuff tst.w ResourceMgrStack.doOverrides(a6) ; <41> Is overriding on? beq.s @endOfChain ; <41> No. don't check the 2 deep bit. ; The requested resource wasnÕt found in the map in A4. Check if the twoDeepBit is set on this ; map, and if it is, search the next map down. move.l (a4),a1 ; Try the next map, but only if this map has twoDeep set. btst #twoDeepBit,mInMemoryAttr(a1) ; Is the twoDeepBit set? beq.s @endOfChain ; ... yes ignore oneDeep, so don't zero handle @notOneDeepMap move.l (a4),a1 move.l mNext(a1),d0 ; Go until the end of the resource chain bne.s @buildLoop @endOfChain move.l (a3),a0 move.l d5,kResourceCount(a0) ; Stash the count @exitCacheResource movem.l (sp)+,d2-d7/a1-a4 ; Restore registers rts ; Return ;_______________________________________________________________________________ ; IsDuplicate determines whether the resource ID pointed to be A2 is already used ; by another resource entry in the cache pointed to by A3. IsDuplicate moveq #1,d0 ; Assume itÕs a duplicate move.w rID(a2),d1 ; Keep ID in a register movem.l a0/d2,-(sp) ; Save A0 & D2 move.w d5,d2 ; Make a copy of the current count move.l (a3),a0 add.w #kCacheHeaderSize,a0 ; Point to cached resource info bra.s @loopEnd ; Let loop fall through if the cache is empty @findDuplicates cmp.w kResourceIDEntry(a0),d1 ; Does the ID match? bne.s @notDuplicate ; No. Try the next entry ; <31> To make the case where a resource is in the System, an application, but not a ; Gibbly work, check to see if the resource map of the cached entry is an override ; map for the resource map of the resource weÕre thinking about putting in the ; cache. The handle to the second resource map is in A4, and the handle to the ; first resource map is in the cache. Call the new routine, DoesCachedMapOverrideCurrentMap, ; to make this determination. We might want to make this a selector off of ; _ResourceDispatch one day if this type of thing needs to be determined a lot. ; ; <47> DoesCachedMapOverrideCurrentMap used to scan the resource chain for duplicates ; until it finds a map that doesnÕt have any override attributes set. The theory ; was that a string of resource maps with override attributes set are associated ; with each other, like Gibblies and the System, or the System and font files. ; This test was too generic, and fails in the case where an application has an ; override map, and the map below the application is a Gibbly or the System. ; In this case, resources in the System and the application override that have ; the same type and ID are considered duplicates of each other, which isnÕt right. ; Now, just look at the two deep bit on resource maps to determine if one is ; associated with another. ; subq #2,sp ; <31> move.l a4,-(sp) ; <31> Resource map handle of current resource move.l kMapHandleEntry(a0),-(sp) ; <31> Resource map handle of resource in cache move.w #kTwoDeepMask,-(sp) ; <45> <47> Scan until a map without the two deep attribute is found bsr DoesCachedMapOverrideCurrentMap ; <31> Go find out if this is true tst.b (sp)+ ; <31> Check the result bnz.s @duplicateID ; <31> The cache entry comes from a resource map which overrides the current resource map, so this resource should be considered a duplicate. @notDuplicate addq #kCacheEntrySize,a0 ; Otherwise, try next cache entry @loopEnd dbra d2,@findDuplicates @idNotInCache moveq #0,d0 ; End of cache, and no duplicates @duplicateID movem.l (sp)+,a0/d2 tst.w d0 ; Set up the condition codes rts ; And return ;_______________________________________________________________________________ ; <31> DoesCachedMapOverrideCurrentMap. Given two resource map handles, this routine ; determines if one is an override map of the other. This is done by traversing ; the resource chain from the second resource map until a map is found that does ; not have the overrideNextMap bit set. If any of the resource maps that are ; visited during the traversal match the first resource map parameter, this routine ; returns that the current map is overriden by the cached map. ; ; <45> Added a parameter that specifies the bit combination to test in the mInAttr field ; of the resource map. Doing this allows this routine to be used by CacheResource ; and RemoveResourceOverride, which require checking different bits. ; DoesCachedMapOverrideCurrentMap DoesCachedMapOverrideStackFrame Record {A6Link},Decr result ds.w 1 ; Space for result paramBegin equ * currentMap ds.l 1 ; Handle to current resource map cachedMap ds.l 1 ; Handle to resource map in cache bitsToTest ds.w 1 ; <45> Bits in mInAttr to test paramSize equ paramBegin - * retAddr ds.l 1 A6Link ds.l 1 EndR With DoesCachedMapOverrideStackFrame link a6,#0 movem.l d1/a0/a1,-(sp) ; <46> move.w #-1,result(a6) ; Assume cachedMap does override currentMap move.l currentMap(a6),a0 move.l cachedMap(a6),a1 move.w bitsToTest(a6),d1 ; <45> @compareMap cmp.l a0,a1 ; Do the maps match? beq.s @gotMatch ; Yes. WeÕve got an override case ; OK, I lied in all the comments up to now. Testing just the overrideNextMap bit isnÕt enough, ; because font resources in the Fonts folder would get counted more than once. To get ; around this, if ANY override bit is set, look at the next map down. move.l (a1),a1 move.b mInMemoryAttr(a1),d0 ; Get override bits and.b d1,d0 ; Mask off everything but the bits of interest bz.s @noMatch ; No itÕs not, and we should stop looking now, too. move.l mNext(a1),d0 ; ItÕs an override map. Get the next map, if there is one. bz.s @noMatch ; No more maps. move.l d0,a1 bra.s @compareMap ; We got to the end of the resource chain or a non-override map without hitting currentMap. ; Therefore, this resource should not be considered a duplicate of the current cache entry. @noMatch clr.w result(a6) @gotMatch movem.l (sp)+,d1/a0/a1 ; <46> Restore used registers unlk a6 move.l (sp)+,d0 ; I saved A0 for a reason, so I canÕt use it hereÉ add.w #paramSize,sp ; Pop off the parameters move.l d0,-(sp) rts ;_______________________________________________________________________________ ; ; Routine: CheckAndFlushFontCache (utility) ; ; Arguments: A4 (input.L) map handle ; ; Called By: OpenResFile, HOpenResFile, OpenRFPerm, CloseResFile ; ; Calls: TypeScan ; ; Function: If the map in A4 has a 'FONT' or 'FOND' resource we invalidate ; the font caches. ;_______________________________________________________________________________ CheckAndFlushFontCache movem.l a0-a4/d0-d5,-(sp) move.l #'FONT',d3 bsr TypeScan bpl.s @doFlush move.l #'FOND',d3 bsr TypeScan bmi.s @dontFlush @doFlush MOVE.L MinusOne,LastSPExtra ; invalidate font cache move.l ExpandMem,a1 move.l ExpandMemRec.emSplineKey(a1),a1 ; Get handle to TrueType globals move.l (a1),a1 ; Point to it. lea splineKeyRec.fondCache(a1),a1 ; Point to candidate cache move.l (a1),a0 _DisposeHandle ; Get rid of this cached entry clr.l (a1)+ move.l (a1),a0 ; Nail the next one too _DisposeHandle clr.l (a1) clr.l LastFOND ; nuke this handle, just in case it was one of the FONDs in this file <52> @dontFlush bsr FlushResourceCache movem.l (sp)+,a0-a4/d0-d5 rts ;_______________________________________________________________________________ ; ; Routine: FlushChangedFONDs ; ; Arguments: a2 - Handle Entry for the resource we are checking ; ; Called By: ChangedResource, AddResource, RmveResource ; Calls: _DisposeHandle ; ; Function: invalidate the 'FOND' candidate list if a 'FOND' resource in the ; candidate cache is being changed ; ; Trashes: nothing ; ; Written by: Dean Yu; rolled in by Scott Boyd and Fred Monroe ;_______________________________________________________________________________ FlushChangedFONDs movem.l a0-a1/d0-d1,-(sp) cmp.l #'FOND',TType(a2) ; Check are we messing w/ a 'FOND' Resource bne.s @notFONDResource ; ItÕs not a FOND ; ; ItÕs a 'FOND'. If the candidate lists have this 'FOND' cached, ; invalidate it. ; move.l ExpandMem,a0 move.l ExpandMemRec.emSplineKey(a0),a0 ; Get handle to TrueType globals move.l (a0),a0 ; Point to it. lea splineKeyRec.fondCache(a0),a0 ; Point to candidate cache move.l (a0),a1 ; Get Candidate in A1 bsr CheckCandidate ; See if this candidate matches the 'FOND' ID that has changed tst.w d1 ; Font family number was left in D0 if handle was not disposed bne.s @notFlushed clr.l (a0) ; Clear out candidate entry @notFlushed move.l 4(a0),a1 ; Check the next one, too bsr CheckCandidate tst.w d1 ; Font family number was left in D0 if handle was not disposed bne.s @notFONDResource clr.l 4(a0) @notFONDResource movem.l (sp)+,a0-a1/d0-d1 rts ; ; Compare the ID of the cached FOND information. If the ID matches the resource that changed, ; invalidate the candidate entry. ; ; Arguments A2 (input.L) resource handle ; A1 (input.L) Candidate to check (possibly nil handle) ; d1 (output.L) result (Z if disposed) ; ; Trashes: d0-d1, A1 ; CheckCandidate moveq #-1,d1 ; Assume handle is not disposed move.l a1,d0 ; Get the handle bz.s @notSameFamily ; Bail out if handle is NIL move.l (a1),d0 ; Get the pointer bz.s @notSameFamily ; Bail again if needed move.l d0,a1 moveq #-1,d1 ; Assume handle is not disposed move.w (a1),d0 ; Fetch the font family number cmp.w RID(a2),d0 ; Compare it against the resource ID of the changed 'FOND' bne.s @notSameFamily ; DonÕt invalidate if not the right ID _DisposeHandle ; If ID matches, dispose the handle moveq #0,d1 ; Mark as handle was disposed @notSameFamily rts ;_______________________________________________________________________________ ; ; Routine: UpdateOverriddenChangedBits (utility) ; ; Arguments: A4 (input.L) map handle ; ; Called By: Anywhere a mapChanged bit is setÉ ; ; Calls: ; ; Function: If the map in A4 overrides another file than we set the changed bit ; in that overridden file. ;_______________________________________________________________________________ UpdateOverriddenChangedBits movem.l a0-a2/a4/d0-d1,-(sp) move.l (a4),a0 move.b mInMemoryAttr(a0),d0 ; Get the override bits andi.b #kAllOverrideAttributesMask,d0 ; This and masks off everything but override bits. If any bits bz.s @exit ; are left in D0, then this map has some override attributes. ; See if this is an override map btst #overrideNextMapBit,d0 ; WeÕve still got our override attributes in D0 bz.s @notAnOverrideMap ; This is an override map, but it might be a font file ; This is an override map. Find the map it overrides. subq #4,sp move.l a4,-(sp) bsr FindOverriddenMap ; trashes a0-a1/d0 move.l (sp)+,a4 ; Save the handle to the overriden map bra.s @setMapChangedOnOverrideMap ; Go set the bit @notAnOverrideMap subq #2,sp move.l a4,-(sp) _IsThisASystemResourceMap ; See if this is a font file tst.b (sp)+ ; Well is it? bz.s @exit ; If itÕs not, then we donÕt know why this map has override bits on it. Just call AddResource, and donÕt set the mapChanged bit anywhere else. move.l SysMapHndl,a4 ; If it is, set the mapChanged bit of the system map @setMapChangedOnOverrideMap move.l (a4),a0 bset #mapChanged,mAttr(a0) ; Mark the overridden map as changed @exit movem.l (sp)+,a0-a2/a4/d0-d1 rts ;_______________________________________________________________________________ ; FindOverriddenMap ; ; Given a handle to a resource override map, find the map it overrides. This routine ; assumes that the map passed in is an override map. ; ; trashes a0-a1/d0 FindOverriddenMap move.l (sp)+,a0 move.l (sp)+,d0 ; Get resource map handle move.l a0,-(sp) @findOverriddenMapLoop move.l d0,a1 move.l (a1),a0 btst #overrideNextMapBit,mInMemoryAttr(a0) ; This bit says whether or not this is an override map bz.s @foundOverriddenMap ; If the bit isnÕt set, then weÕve got the overridden map move.l mNext(a0),d0 ; Otherwise, look at the next map down bnz.s @findOverriddenMapLoop move.l d0,a1 ; If we didnÕt find the overridden map before reaching the end of the chain, return nil. @foundOverriddenMap move.l a1,4(sp) ; Return result on the stack rts ; CSS Add the following routine for rsrczoneinit patch ;_______________________________________________________________________________ ; FlushResourceCache disposes the resource cache handle to force the cache to ; be rebuilt next time _CountResources or _GetIndResource is called. The cache ; will be flushed whenever the offset to a resource stored in the cache may become ; invalid (when resources are added or removed from the map or when the map is updated or ; written to disk) and when files are opened or closed which may cause the count to ; become invalid. ; ; should preserve a0É FlushResourceCache movem.l d0/a0,-(sp) move.l ExpandMem,a0 clr.w ExpandMemRec.emLastMapOverridden(a0) ; And force an override synchronization next time CSS move.l ExpandMemRec.emResourceCache(a0),d0 ; Get resource cache handle beq.s @noExpandMem ; DoesnÕt exist clr.l ExpandMemRec.emResourceCache(a0) ; Zero it out move.l d0,a0 _DisposeHandle ; Get rid of the cache @noExpandMem movem.l (sp)+,d0/a0 rts EndProc END ;=== End Of File ========================================================================