mac-rom/Patches/GreggyBitsDefProc.a

299 lines
11 KiB
Plaintext
Raw Normal View History

;
; File: GreggyBitsDefProc.a
;
; Contains: Decompress defProc for GreggyBits decompression "'dcmp'(2)"
;
; Written by: Greg Marriott
;
; Copyright: <09> 1990-1991 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <6> 12/18/91 pvh Remove '040 cache flushing from here and move to
; DeCompressorPatch.a where it will do more good for mankind.
; <5> 12/10/91 pvh Added cache flushing for '040s at end of decompression. This
; appears to clear up boot problems on the Quadras.
; <4> 1/30/91 gbm sab, #38: Change the name of one of the decompressor header
; files (because Sheila said it was okay)
; <3> 12/14/90 dba & sab: make a small optimization to the decompressor
; <2> 9/4/90 gbm add new calling interface for new defProcs (like this one)
; <1> 9/3/90 gbm first checked in
; 9/3/90 gbm Newly checked in today
;
; To Do:
;
LOAD 'StandardEqu.d'
include 'DecompressorPatchEqu.a'
IF &TYPE('forCompressor')='UNDEFINED' THEN
forCompressor: SET 0
ENDIF
;
; First, we have the offset table for the three entry points used by the decompress patch
;
EntryPointTable proc
import PrepareForDecompression, WordForByte, CleanUpAfterDecompression
dc.w PrepareForDecompression-EntryPointTable
dc.w WordForByte-EntryPointTable
dc.w CleanUpAfterDecompression-EntryPointTable
endproc
;---------------------------------------------------------------------------------
;
; RECORD PrepareForDecompressionFrame
;
; Stack frame template for PrepareForDecompression routine
;
;---------------------------------------------------------------------------------
PrepareForDecompressionFrame RECORD {A6Link},DECR
StartParams EQU *
header DS.L 1 ; extended header for this resource
ParamSize EQU StartParams-*
Return DS.L 1
A6Link DS.L 1
; locals go here
ENDRSize
;---------------------------------------------------------------------------------
;
; PROCEDURE PrepareForDecompression( header : Ptr ); {ptr to an extended resource header}
;
; This is the routine called by the decompress patch to tell us to get ready
; for decompression. This is where we allocate extra storage, etc...
; But, this defproc doesn't NEED any extra storage, so we don't do anything.
;
;---------------------------------------------------------------------------------
PrepareForDecompression Proc Export
With PrepareForDecompressionFrame
; I guess we can just leave...
movem.l D4/A6, BootTmp8 ; this is very important
move.l (sp)+, a0 ; get return address
add.l #ParamSize, sp ; pop parameters
jmp (a0) ; return to caller
EndWith
EndProc
;---------------------------------------------------------------------------------
;
; RECORD CleanUpAfterDecompressionFrame
;
; Stack frame template for CleanUpAfterDecompression routine
;
;---------------------------------------------------------------------------------
CleanUpAfterDecompressionFrame RECORD {A6Link},DECR
StartParams EQU *
header DS.L 1 ; extended header for this resource
ParamSize EQU StartParams-*
Return DS.L 1
A6Link DS.L 1
; locals go here
ENDRSize
;---------------------------------------------------------------------------------
;
; PROCEDURE CleanUpAfterDecompression( header : Ptr ); {ptr to an extended resource header}
;
; This is the routine called by the decompress patch to tell us to clean up
; after decompression. This is where we deallocate extra storage, etc...
; But, this defproc doesn't NEED any extra storage, so we don't do anything.
;
;---------------------------------------------------------------------------------
CleanUpAfterDecompression Proc Export
With CleanUpAfterDecompressionFrame
; I guess we can just leave...
move.l BootTmp8, A0 ; this is just as important
add.l BootTmp8+4, A0
move.l (sp)+, a0 ; get return address
add.l #ParamSize, sp ; pop parameters
jmp (a0) ; return to caller
EndWith
EndProc
;---------------------------------------------------------------------------------
;
; RECORD WordForByteFrame
;
; Stack frame template for WordForByte routine
;
;---------------------------------------------------------------------------------
WordForByteFrame RECORD {A6Link},DECR
StartParams EQU *
source DS.L 1 ; get compressed data here,
destination DS.L 1 ; and put it here
header DS.L 1 ; extended header for this resource
ParamSize EQU StartParams-*
Return DS.L 1
A6Link DS.L 1
; locals go here
ENDRSize
;
; Register equates I COULD have used in decompression
;
;
;scratch EQU d0
;numberOfWords EQU d1
;numberOfRuns EQU d1
;wordsInLastRun EQU d2
;runBitMap EQU d3
;runCount EQU d4
;extraByteFlag EQU d5
;source EQU a0
;byteTable EQU a1
;destination EQU a2
;extendedHeader EQU a3
;endOfSource EQU a4
;---------------------------------------------------------------------------------
;
; PROCEDURE WordForByte( source, destination, extHeader : Ptr ); (not MemoryMgr blocks, just addresses)
;
; This function takes data and decompresses it. The data is moved from source to
; destination, decompressing bytes into words. If a dynamic byte table is included
; in the data, it is copied into the table buffer (contained herein) before decompression.
; A pointer to the extended header is also provided, so that various flags and whatnot will
; be available to the decompress routine.
;
;---------------------------------------------------------------------------------
WordForByte Proc Export
With WordForByteFrame, ExtendedResource
link a6, #WordForByteFrame.SIZE
movem.l a0-a4/d0-d5, -(SP)
move.l header(a6), a3 ; flags and shit be here...
move.l source(a6), a0
move.l destination(a6), a2
@testForTable
btst #byteTableSaved, compressFlags(a3)
beq.s @noByteTableSaved
moveq #0, d0
move.b byteTableSize(a3), d0 ; get the size, in words, of the byte table
addq.w #1, d0 ; adjust it to "real" numbers (not zero based)
add.w d0, d0 ; make it bytes
lea DynamicTable, a1 ; point to the start of our storage
move.w d0, d1 ; save size a sec...
_BlockMove ; copy the table
adda.w d1, a0 ; move source pointer past table data
bra.s @testForOddLength
@noByteTableSaved
lea StaticTable, a1 ; point to the start of the static table
@testForOddLength
move.l actualSize(a3), d1 ; get the real size, and figure out the special cases
lsr.l #1, d1 ; but first, turn data length into number of words of uncompressed data
scs d5 ; indicate no extra byte is there
@testForBitMap
btst #bitmappedData, compressFlags(a3)
bne.s DoBitMappedData
DoNonBitMappedData
move.l a0, a4
add.l d1, a4 ; point a4 past last byte of source data
@again
moveq #0, d0
move.b (a0)+, d0 ; get byte
add.w d0, d0 ; turn it into an index
move.w (a1, d0.w), (a2)+ ; move word to destination
cmp.l a0, a4
bhi.s @again ; not at end, do it again
DoDanglingByte
tst.b d5 ; is there one more byte to move?
beq.s AllDone ; no, leave
move.b (a0), (a2) ; yes, move it and leave
bra.s AllDone
DoBitMappedData
move.l d1, d2 ; get number of uncompressed words we should do
andi.l #$7, d2 ; MOD 8 - d2 now has the number of words in the last run
lsr.l #3, d1 ; DIV 8 - d1 now has the number of 8 word runs to decompress
bra.s @endOfRun
@do8 ; if we're making this routine for the compressor
IF forCompressor THEN ; to do its reality check, then make sure
cmp.l a0, a2 ; the source and dest pointers never cross...
bls.s @pointersOK ; if they do, just leave, because the comparison
bra AllDone ; routine will show that this decompressed
@pointersOK ; resource doesn't match the original...
ENDIF
moveq #8-1, d4 ; otherwise, load up for another run
move.b (a0)+, d3 ; get bitmap
beq.s @fast8 ; if the bitmap's empty, all 16 words are uncompressed
@doNextDatum
add.b d3, d3 ; shift map over one
bcs.s @doCompressed ; bit was set, so do it the hard way
move.b (a0)+, (a2)+ ; bit wasn't set, so do it the easy way
move.b (a0)+, (a2)+ ; bit wasn't set, so do it the easy way, part II
dbra d4, @doNextDatum ; loop around
@endOfRun
subq.l #1, d1 ; subtract one from run count (we may go past -1 because of last run)
bpl.s @do8 ; and go do another batch of 16
bra.s @doLastRun ; when we fall below zero, bail out
@fast8
move.b (a0)+, (a2)+
move.b (a0)+, (a2)+
dbra d4, @fast8
bra.s @endOfRun
@doCompressed
moveq #0, d0
move.b (a0)+, d0 ; get compressed datum
add.w d0, d0 ; make it an index into byte table
move.w (a1, d0.w), (a2)+ ; move word from table to destination
@lastEntry
dbra d4, @doNextDatum ; loop around
bra.s @endOfRun ; branch to end, prepare another run
@doLastRun
move.w d2, d4 ; load up number of words to move
beq.s DoDanglingByte ; there aren<65>t any more words, just think about a last byte
moveq #0, d2 ; and make sure we don<6F>t do this again...
move.b (a0)+, d3 ; get mask for this run
bra.s @lastEntry ; enter through bottom of dbra, 'cause the count is 1 based
AllDone
; I guess we can just leave...
movem.l (sp)+, a0-a4/d0-d5
unlk a6
move.l (sp)+, a0 ; get return address
add.l #ParamSize, sp ; pop parameters
jmp (a0) ; return to caller
StaticTable
DC.W $0000, $0008, $4EBA, $206E, $4E75, $000C, $0004, $7000, $0010, $0002, $486E, $FFFC, $6000, $0001, $48E7, $2F2E
DC.W $4E56, $0006, $4E5E, $2F00, $6100, $FFF8, $2F0B, $FFFF, $0014, $000A, $0018, $205F, $000E, $2050, $3F3C, $FFF4
DC.W $4CEE, $302E, $6700, $4CDF, $266E, $0012, $001C, $4267, $FFF0, $303C, $2F0C, $0003, $4ED0, $0020, $7001, $0016
DC.W $2D40, $48C0, $2078, $7200, $588F, $6600, $4FEF, $42A7, $6706, $FFFA, $558F, $286E, $3F00, $FFFE, $2F3C, $6704
DC.W $598F, $206B, $0024, $201F, $41FA, $81E1, $6604, $6708, $001A, $4EB9, $508F, $202E, $0007, $4EB0, $FFF2, $3D40
DC.W $001E, $2068, $6606, $FFF6, $4EF9, $0800, $0C40, $3D7C, $FFEC, $0005, $203C, $FFE8, $DEFC, $4A2E, $0030, $0028
DC.W $2F08, $200B, $6002, $426E, $2D48, $2053, $2040, $1800, $6004, $41EE, $2F28, $2F01, $670A, $4840, $2007, $6608
DC.W $0118, $2F07, $3028, $3F2E, $302B, $226E, $2F2B, $002C, $670C, $225F, $6006, $00FF, $3007, $FFEE, $5340, $0040
DC.W $FFE4, $4A40, $660A, $000F, $4EAD, $70FF, $22D8, $486B, $0022, $204B, $670E, $4AAE, $4E90, $FFE0, $FFC0, $002A
DC.W $2740, $6702, $51C8, $02B6, $487A, $2278, $B06E, $FFE6, $0009, $322E, $3E00, $4841, $FFEA, $43EE, $4E71, $7400
DC.W $2F2C, $206C, $003C, $0026, $0050, $1880, $301F, $2200, $660C, $FFDA, $0038, $6602, $302C, $200C, $2D6E, $4240
DC.W $FFE2, $A9F0, $FF00, $377C, $E580, $FFDC, $4868, $594F, $0034, $3E1F, $6008, $2F06, $FFDE, $600A, $7002, $0032
DC.W $FFCC, $0080, $2251, $101F, $317C, $A029, $FFD8, $5240, $0100, $6710, $A023, $FFCE, $FFD4, $2006, $4878, $002E
DC.W $504F, $43FA, $6712, $7600, $41E8, $4A6E, $20D9, $005A, $7FFF, $51CA, $005C, $2E00, $0240, $48C7, $6714, $0C80
DC.W $2E9F, $FFD6, $8000, $1000, $4842, $4A6B, $FFD2, $0048, $4A47, $4ED1, $206F, $0041, $600C, $2A78, $422E, $3200
DC.W $6574, $6716, $0044, $486D, $2008, $486C, $0B7C, $2640, $0400, $0068, $206D, $000D, $2A40, $000B, $003E, $0220
DynamicTable
DCB.W 256, 0
EndProc
End