Elliot Nunn 5b0f0cc134 Bring in CubeE sources
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included.

The Tools directory, containing mostly junk, is also excluded.
2017-12-26 10:02:57 +08:00

645 lines
25 KiB
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

; File: DeCompressorPatch.a
; By Donn Denman
; Contains: patch to Resource Manager's CheckLoad hook for resource decompression.
; Copyright: © 1990-1991 by Apple Computer, Inc., all rights reserved.
; Change History (most recent first):
; <18> 12/18/91 pvh Add '040 cache flushing at a point after the resources have been
; decompressed. This helps executable code out a great deal.
; Catches both DonnBits & GreggyBits (and any new ones that may
; come along).
; <17> 2/7/91 gbm csd, #82402: Make this patch reentrant.
; <16> 1/30/91 gbm sab, #38: Change the name of one of the decompressor header
; files (because Sheila said it was okay)
; <15> 12/20/90 gbm (dba) Reintroduce the saving and restoring of some key Resource
; Manager globals. This will make decompression work.
; <14> 10/30/90 dba only accept decompressor defprocs from resource files with a
; special bit set
; <13> 9/25/90 gbm Stop caching what we think was the last defproc... this was
; bogus
; <12> 9/4/90 gbm make a new calling interface for new defProcs
; <11> 9/3/90 gbm add knowledge of new header types. Types newer (higher) than 8
; have a different format. DefProcs called when the new header is
; present have a calling interface different from previous
; defprocs.
; <10> 9/2/90 csd Made the resource handle NIL if we donÕt have enough memory to
; load the resource
; <9> 8/31/90 stb Change var table allocation from NewPtr to NewHandle. ItÕs
; faster and wonÕt burp the new resource handle.
; <8> 3/23/90 DD Fixed a bug in which the variable table was not being made large
; enough.
; <7> 3/9/90 DD Fixed both decompression and SizeRsrc patch to be robust about
; resources with the extended attributes bit that don't have the
; right signiture. Note that MacPaint has the 'compressed' bit
; set on all of their resources.
; <6> 2/28/90 DD major rewrite includes decompress in place, and separate
; decompress defproc 'dcmp'
; <6> 2/2/90 DD Changed the error code returned when a resource can't be
; decompressed to CantDecompress: -186, new from SysErr.a
; <5> 1/29/90 DD Removed a userbreak so you won't go into Macsbug during an error
; condition.
; <4> 1/18/90 DD reorganized the resource header for extended attribute
; resources, and compressed flavor extended attribute resources
; <3> 1/18/90 DD Updated the source to match a newer version with several bug
; fixes.
; <2> 1/18/90 DD Removed a user break, and changed the message in a user break
; that informs of an out-of-memory condition
; <1> 1/17/90 DD Adding for the first time into BBS.
ROMVersions MacPlus, MacSE, MacII, Esprit, Aurora
; Location of the _Read trap in Resource Manager's RdData routine.
FromReadInResMgr Bind (MacPlus,$14250),(MacSE,$E864),(MacII,$1319E),(Esprit,$147F6),(Aurora,$1BA1A)
; Location of the Bsr RdData in Resource Manager's SizeRsrc routine.
FromSizeRsrc Bind (MacPlus,$141DA),(MacSE,$E7EE),(MacII,$13128),(Esprit,$14780),(Aurora,$1B9A4)
; Location of the Bsr SizeRsrc in Resource Manager's SizeResource routine - the _SizeRsrc code.
FromSizeResource Bind (MacPlus,$1487A),(MacSE,$EE9C),(MacII,$137D6),(Esprit,$14E2E),(Aurora,$1C052)
; Location of the second Bsr RdData in Resource ManagerÕs NewMap routine.
FromNewMap Bind (MacPlus,$136B4),(MacSE,$DCB0),(MacII,$125E4),(Esprit,$13C54),(Aurora,$1AE6C)
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
localSize EQU *
ENDR ;<17>
DeCompression PROC
EXPORT OldCheckLoadJump,MyCheckLoad
With ExtendedResource, ExtResRecord, VarTableRec, ResourceTemplate, DecompressionLocals
; ReadResData - Read the resource data for D0 bytes into the buffer (A0).
; Entry: D0 - number of bytes to read.
; D1 - relative data location within the resource data block.
; A0 - pointer to the data buffer.
; A4 - resource map handle.
; A6 - LINKed locals for decompression <17>
; Exit: D0 - result code.
; A0 - pointer to the header data.
; all other registers saved.
Lea ResHeaderBuffer(a6),A0 ; <17>
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
; Buffer for I/O with read.
;starting with change <17>, this is all on a local stack frame (for recursion)
; DS.B ResTemplateSize ;room for a ExtResRecord
; DS.B 1 ; boolean set if we're doing "old" decompression
; 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.
; Slight modification to above.... we have our own locals LINKed on A6
* MyCheckLoad
* 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 OldCheckLoad.
* Remember ResLoad, Clear ResLoad.
* Call OldCheckLoad 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
* Reister 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>
;is it compressed? Flag that it isn't in case it gets modified and written.
BTst.B #resExtended,RAttr(A2)
BNZ.S TestResHandle ;no, then just do the old checkload stuff.
AERROR 'The decompression patch for the CheckLoad hook needs to be reworked to go into ROM!'
Jmp (0).L ;gets stuffed with the old address.
; if there is alredy data in the handle, then just call old checkload.
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.S OldCheckLoadJump ; it has data, so no need to load, or decompress.
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.S OldCheckLoadJump ;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?
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 #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,ResHeader.signiture(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.S OldCheckLoadJump ;read in the data, now that resLoad is restored.
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)
if DoDebug then
BNZ @SkipDebugBreak
Break 'Simple Extended Resource'
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
move.w ResHeader.defprocID(a0), d5 ; get defProc
; 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
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
move.l (a1),a1 ;get map pointer
move.l mNext(a1),a1 ;go on to the next file in the chain
bra.s @tryMap
; remember the defproc handle. (mostly 'cause we don't have any registers left...)
Lea DefProcHandle,A1 ;stuff away the defproc ID
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.
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.
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.
; Remember the current heap zone, and switch to the zone of the compressed handle.
_GetZone ;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
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
_SetZone ; 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.
; 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 @ExitPastHSetState ;exit if an error happened. Skip HSetState <10>
; 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 @Exit
; if it is not a compressed resource, then we are done.
BTst #resCompressed,ResHeaderBuffer+ExtResRecord.ResHeader.extendedAttributes(a6) ;compressed resource? <17>
Beq @Exit
; 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
AddQ.L #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,A0 ;get the defproc handle.
Move.L (A0),A0
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 @cutBackHandle
pea ResHeaderBuffer+ExtResRecord.ResHeader(a6) ; header ptr <17>
move.l DefProcHandle, a0 ;
move.l (a0), a0 ;
adda.w 0(a0), a0 ; move to offset of "Prepare" routine
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, a0 ;
move.l (a0), a0 ;
adda.w 2(a0), a0 ; move to offset of "Decompress" routine
jsr (a0) ; call defProc "Decompress" routine
pea ResHeaderBuffer+ExtResRecord.ResHeader(a6) ; header ptr <17>
move.l DefProcHandle, a0 ;
move.l (a0), a0 ;
adda.w 4(a0), a0 ; move to offset of "Done" routine
jsr (a0) ; call defProc "Done" routine
@cutBackHandle ; 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.
Move.L A5,A0 ;The following bit-smashing is 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
@ExitPastHSetState ; <10>
Move.L D3,A0
_SetZone ; 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 @not040 ; If we are then <18>
jsr ([jCacheFlush]) ; flush data cache for consistency! <18>
; we should really do this cache line by line for speed... maybe later <18>
MoveM.L (SP)+,D3-D7/A4-A5
UNLK A6 ; <17>
; We got an error cloning the handle, or creating the unpacked handle. Toss the clone (even if Nil).
Move.W #MemFullErr,D2 ;not enough to allocate var table
Move.L A5,A0
*** 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
; Storage
DefProcHandle DC.L 0 ;current defProc.
; SizeRsrc patch
SizeRsrcStack Record 0
dispatcherReturn DS.L 1 ;return address to the dispatcher
dispatcherRegs DS.L 4 ;dispatcher saves five regs. We ignore the first four.
oldRegisterA2 DS.L 1 ;register A2 is saved here by the dispatcher.
dispatcherResult DS.L 1 ;dispatcher pops this result long.
readReturn DS.L 1 ;return address for the _Read trap.
RdResgisters DS.L 4 ;four registers saved by RdData.
RdDataReturn DS.L 1 ;return address (to SizeRsrc?)
SzResgisters DS.L 4 ;four registers saved by SizeRsrc.
RdDataResult DS.L 1 ;room for result from RdData
SizeRsrcReturn DS.L 1 ;return address (to SizeResource?)
With ExtendedResource, ExtResRecord, SizeRsrcStack
Export ReadDecompression
bra.s SkipOldRead ;the special header here for patch protector
JumpOldRead BackToTrap Read ;now do the old read.
CmpBind FromReadInResMgr,readReturn(SP) ;check return from _Read -- coming from resource manager?
BNE.S JumpOldRead ;nope, skip the patch.
CmpBind FromNewMap,RdDataReturn(SP) ;will RdData return to NewMap?
BEQ.S NewMapPatch ;yes, do the NewMap patch
CmpBind FromSizeRsrc,RdDataReturn(SP) ;will RdData return to SizeRsrc?
BNE.S JumpOldRead ;nope, skip the patch.
CmpBind FromSizeResource,SizeRsrcReturn(SP) ;will SizeRsrc return to SizeResource?
BNE.S JumpOldRead ;nope, skip the patch.
; now we know that we are about to read the length for _SizeRsrc on an extended resource.
Move.L oldRegisterA2(SP),A1 ;rebuild A2 here.
Add.L (A4),A1 ; restore to a pointer <30may85> BBM
BTst.B #resExtended,RAttr(A1) ;is this an extended resource?
Bz.S JumpOldRead ;nope, skip the patch.
; make sure this is really a compressed resource by reading in the header data, and testing for our signiture.
LINK A6, #localSize ; <17>
MoveM.L D1/A0,-(SP)
MoveQ #ResHeaderSize,D0 ;amount we wish to read.
Move.L RLocn(A1),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.signiture(A0) ;is it really an extended resource?
MoveM.L (SP)+,D1/A0
UNLK A6 ; <17>
BNE.S JumpOldRead ;didn't match, then just do old sizersrc.
; 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,ioPosOffset(A0) ;bump the offset by our header and a long.
BRA.S JumpOldRead ;go do the read
; we have already read in the map header, and are about to read in the extended attributes
move.l a0,-(sp)
move.l (a4),a0 ;get pointer to the map
clr.b mInMemoryAttr(a0) ;clear attributes that are set at run-time only
move.l (sp)+,a0
BRA.S JumpOldRead ;go do the read