mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2024-12-28 01:29:20 +00:00
0ba83392d4
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.
645 lines
25 KiB
Plaintext
645 lines
25 KiB
Plaintext
;
|
||
; 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.
|
||
|
||
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
|
||
|
||
;
|
||
; Buffer for I/O with read.
|
||
;starting with change <17>, this is all on a local stack frame (for recursion)
|
||
;ResHeaderBuffer
|
||
; DS.B ResTemplateSize ;room for a ExtResRecord
|
||
;DoDonnDecompress
|
||
; DS.B 1 ; boolean set if we're doing "old" decompression
|
||
; ALIGN
|
||
;_______________________________________________________________________________
|
||
; 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>
|
||
*
|
||
********************************************************************************************
|
||
|
||
MyCheckLoad
|
||
|
||
;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.
|
||
|
||
IF ForROM THEN
|
||
AERROR 'The decompression patch for the CheckLoad hook needs to be reworked to go into ROM!'
|
||
ELSE
|
||
OldCheckLoadJump
|
||
Jmp (0).L ;gets stuffed with the old address.
|
||
ENDIF
|
||
|
||
; if there is alredy 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.S OldCheckLoadJump ; it has data, so no need to load, or decompress.
|
||
|
||
DeCompressor
|
||
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?
|
||
@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 #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.
|
||
|
||
@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)
|
||
;Debugging
|
||
if DoDebug then
|
||
BNZ @SkipDebugBreak
|
||
Break 'Simple Extended Resource'
|
||
@SkipDebugBreak
|
||
endif
|
||
;Debugging
|
||
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,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.
|
||
|
||
@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.
|
||
|
||
_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
|
||
|
||
@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
|
||
_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.
|
||
@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 @ExitPastHSetState ;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 @Exit
|
||
@NoReadError
|
||
|
||
; 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
|
||
@HaveVarSize
|
||
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
|
||
|
||
@dontCallDonn
|
||
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.
|
||
|
||
@Exit
|
||
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>
|
||
@not040
|
||
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
|
||
|
||
********************************************************************************************
|
||
|
||
; 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?)
|
||
EndR
|
||
|
||
With ExtendedResource, ExtResRecord, SizeRsrcStack
|
||
Export ReadDecompression
|
||
ReadDecompression
|
||
bra.s SkipOldRead ;the special header here for patch protector
|
||
JumpOldRead BackToTrap Read ;now do the old read.
|
||
SkipOldRead
|
||
|
||
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
|
||
|
||
NewMapPatch
|
||
|
||
; 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
|
||
|
||
EndWith
|
||
ENDP
|
||
|