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.
439 lines
12 KiB
Plaintext
439 lines
12 KiB
Plaintext
;
|
|
; File: DeCompressDefProc1.a
|
|
; By Donn Denman
|
|
;
|
|
; Contains: parts of the decompress defprocs that are common to all.
|
|
;
|
|
; Copyright: © 1990 by Apple Computer, Inc., all rights reserved.
|
|
;
|
|
; Change History (most recent first):
|
|
;
|
|
; <4> 8/14/90 DD Changed variable lookup at FetchData and assignment at
|
|
; RememberData to use unsigned word offsets.
|
|
; <3> 7/24/90 gbm Fix branches to next instruction, but don't break debug mode...
|
|
; :)
|
|
; <2> 4/18/90 DD Added RunLength Encoding and Delta Encoding variations.
|
|
; <1> 4/12/90 DD first checked in today
|
|
; BBS versions above:
|
|
;___________________________________________________________________________________________________
|
|
|
|
|
|
********************************************************************************************
|
|
*
|
|
* Procedure UnPackData(SourcePtr, DestPtr, VarTable: ptr; VarTableSize: Longint);
|
|
*
|
|
* Description: Unpack the data from the source pointer to the dest pointer.
|
|
* The unpacking is automatically terminated when the end token is reached.
|
|
*
|
|
*
|
|
********************************************************************************************
|
|
UnPackFrame Record {A6Link},Decr
|
|
SourcePtr DS.L 1
|
|
DestPtr DS.L 1
|
|
VarTablePtr DS.L 1
|
|
VarTableSize DS.L 1
|
|
ReturnAddress DS.L 1
|
|
A6Link DS.L 1
|
|
LocalSize DS.L 0
|
|
EndR
|
|
With UnpackFrame
|
|
|
|
UnPackData
|
|
Link A6,#LocalSize ;do the unpack from ptr A0 into pointer in A1.
|
|
MoveM.L D0-D3/A0-A4,-(SP)
|
|
|
|
; Set up the registers, for fast handling.
|
|
|
|
Move.L SourcePtr(A6),A4 ;input stream.
|
|
Move.L DestPtr(A6),A1 ;output stream.
|
|
Lea CodeDispatchTable,A2 ;dispatch table.
|
|
|
|
Move.L VarTablePtr(A6),A3 ;variable table.
|
|
Move.L VarTableSize(A6),D0 ; table size.
|
|
Bsr InitRemember ;init the var table.
|
|
Bra UnpackLoop ; now go to the unpack loop.
|
|
|
|
ExitUnpack
|
|
MoveM.L (SP)+,D0-D3/A0-A4
|
|
UnLk A6
|
|
Move.L (SP)+,A0
|
|
Add #SourcePtr-ReturnAddress,SP
|
|
Jmp (A0)
|
|
|
|
EndWith
|
|
|
|
********************************************************************************************
|
|
*
|
|
* GetEncodedValue
|
|
*
|
|
* Description: gets the value pointed to by A4 into D0.L. The values are encoded:
|
|
*
|
|
* Tag Range computation method
|
|
* --- ----- ------------------
|
|
* 0..127 0,127 Tag[0]
|
|
* 128..254 -16384,16127 (Tag[0]-$C0)*$100+Tag[1]
|
|
* 255 same as Long Tag[1]<<24 + Tag[2]<<16 + Tag[3]<<8 + Tag[4]
|
|
*
|
|
* Input: A4: pointer to tags.
|
|
*
|
|
* Output: A0: points past tags.
|
|
* D0: value long.
|
|
*
|
|
*
|
|
********************************************************************************************
|
|
GetEncodedValue Head
|
|
|
|
|
|
; try byte encoding, cuz it is so easy.
|
|
|
|
MoveQ #0,D0
|
|
Move.B (A4)+,D0
|
|
|
|
Bpl.S @HaveValue ;got the result already.
|
|
|
|
; is it long encoded?
|
|
|
|
Cmp.B #FourByteValue,D0 ;long?
|
|
Beq.S @FetchLong ;yep, that's fairly easy too.
|
|
|
|
; word encoded value.
|
|
|
|
Sub.W #TwoByteValue*3/2,D0 ;cut back the range, toggle the psuedo sign bit.
|
|
Asl.W #8,D0 ;shift by a byte (*256).
|
|
Asl.W #1,D0 ;shift away the top bit.
|
|
ASR.W #1,D0 ;sign extend the top bit.
|
|
Move.B (A4)+,D0 ;get the next byte.
|
|
Ext.L D0 ;sign extend to a long value.
|
|
Bra.S @HaveValue
|
|
|
|
; long encoding
|
|
|
|
@FetchLong
|
|
Move.B (A4)+,D0 ;add in the next byte.
|
|
Asl.W #8,D0 ;shift by a byte (*256).
|
|
Move.B (A4)+,D0 ;add in the next byte.
|
|
Asl.L #8,D0 ;shift by a byte (*256).
|
|
Move.B (A4)+,D0 ;add in the next byte.
|
|
Asl.L #8,D0 ;shift by a byte (*256).
|
|
Move.B (A4)+,D0 ;add in the next byte.
|
|
|
|
@HaveValue
|
|
Tail
|
|
|
|
;
|
|
; CopyWithLength - copy the data following an encoded length.
|
|
;
|
|
CopyWithLength
|
|
Bsr GetEncodedValue ;get the value into D0.
|
|
IF delta=2 THEN
|
|
Add.W D0,D0 ;double the value if we are processing word chucks.
|
|
EndIF
|
|
;BRA.S CopyData ;fall through
|
|
;
|
|
; CopyData - copy the data already knowing the word length.
|
|
;
|
|
CopyData
|
|
Bra.S @Sub1FirstTime
|
|
@CopyData
|
|
Move.B (A4)+,(A1)+ ;copy a byte.
|
|
@Sub1FirstTime
|
|
DBRA D0,@CopyData
|
|
Rts
|
|
|
|
;
|
|
; RememberLiteral - copy the data already knowing the word length.
|
|
; Also add this literal to the Var Table.
|
|
;
|
|
RememberLiteral
|
|
Bsr.S RememberData ;stuff the data pointed to by A4, for length D0 into the var table.
|
|
; fall through to CopyLiteralAndLoop
|
|
;
|
|
; CopyLiteralAndLoop - copy the data pointed to by the input into the output and loop.
|
|
;
|
|
CopyLiteralAndLoop
|
|
Bsr.S CopyData
|
|
Bra UnpackLoop
|
|
|
|
;
|
|
; RememberWithLength - copy the data preceeded by a byte length.
|
|
; Also add this literal to the Var Table.
|
|
;
|
|
RememberWithLength
|
|
Bsr GetEncodedValue ;get the value into D0.
|
|
IF delta=2 THEN
|
|
Add.W D0,D0 ;double the value if we are processing word chucks.
|
|
EndIF
|
|
Bsr.S RememberData ;stuff the data pointed to by A4, for length D0 into the var table.
|
|
Bra.S CopyData
|
|
|
|
;
|
|
; InitRemember - Init the var table.
|
|
; Entry: A3 - Var Table.
|
|
; D0 - Table size.
|
|
;
|
|
InitRemember
|
|
Move.W D0,VarsList(A3) ;first entry points to the end of the table.
|
|
Move.W #2+VarsList,NextVarIndex(A3) ;point to the next var entry.
|
|
Rts
|
|
|
|
;
|
|
; RememberData - stuff the data pointed to by A4, for length D0 into the var table.
|
|
;
|
|
; Entry: A4 - Pointer to the data.
|
|
; D0 - length of the data.
|
|
; A3 - Var Table.
|
|
;
|
|
; Exit: A1,D0 - preserved.
|
|
; A0,D1 Trashed.
|
|
;
|
|
RememberData
|
|
MoveM.L D0/A1,-(SP)
|
|
|
|
MoveQ #0,D1
|
|
Move.W NextVarIndex(A3),D1 ;get the index into the next var.
|
|
AddQ.W #2,NextVarIndex(A3) ;bump the index.
|
|
Lea -2(A3,D1.L),A0 ;point to the previous data offset.
|
|
Move.W (A0)+,D1 ;it defines where my new string must end.
|
|
Sub.W D0,D1 ;compute my new offset.
|
|
Move.W D1,(A0) ;put my offset in place.
|
|
; Debugging
|
|
IF DoDebug > 0 THEN
|
|
Lea 0(A3,D1.L),A1 ;point to my data loc.
|
|
Cmp.L A0,A1
|
|
BGT.S @NoOverFlow
|
|
BreakError 'Variable Table Over Flow!'
|
|
@NoOverFlow
|
|
ENDIF
|
|
; Debugging
|
|
|
|
Lea 0(A3,D1.L),A0 ;point to my data loc.
|
|
Move.L A4,A1
|
|
Bsr.S BlockMoveBytes
|
|
|
|
MoveM.L (SP)+,D0/A1
|
|
Rts
|
|
|
|
;
|
|
; BlockMoveBytes - block moves bytes from (A1)+ to (A0)+ for D0.W.
|
|
;
|
|
BlockMoveBytes
|
|
Bra.S @Sub1FirstTime
|
|
@CopyData
|
|
Move.B (A1)+,(A0)+ ;copy a byte.
|
|
@Sub1FirstTime
|
|
DBRA D0,@CopyData
|
|
Rts
|
|
|
|
;
|
|
; ReuseByte2Length - Reuse the data indexed by the following byte, to add 256 to.
|
|
;
|
|
ReuseByte2Length
|
|
MoveQ #0,D0
|
|
Move.B (A4)+,D0 ;get the length from the input stream
|
|
Add.W #Max1ByteReuse+256,D0 ;bump by the number of vars we can ref in one byte.
|
|
Bra.S FetchData ;call FetchData.
|
|
;
|
|
; ReuseWordLength - copy the data following a word length.
|
|
;
|
|
ReuseWordLength
|
|
MoveQ #0,D0
|
|
Move.B (A4)+,D0 ;get the length from the input stream
|
|
Asl.W #8,D0 ;shift into high byte.
|
|
Bra.S ReuseLowByte
|
|
;
|
|
; ReuseByteLength - Reuse the data indexed by the following byte.
|
|
;
|
|
ReuseByteLength
|
|
MoveQ #0,D0
|
|
ReuseLowByte
|
|
Move.B (A4)+,D0 ;get the length from the input stream
|
|
Add.W #Max1ByteReuse,D0 ;bump by the number of vars we can ref in one byte.
|
|
;Bra.S FetchData ;call FetchData.
|
|
|
|
;
|
|
; FetchData - retrieve the data from index D0 of the var table.
|
|
;
|
|
; Entry: A1 - Pointer to the output stream.
|
|
; D0 - index the data.
|
|
; A3 - Var Table.
|
|
;
|
|
; Exit: A0,D0,D1 Trashed.
|
|
;
|
|
FetchData
|
|
Add.W D0,D0 ;make the index into an offset.
|
|
; Debugging
|
|
IF DoDebug > 0 THEN
|
|
Cmp.W NextVarIndex(A3),D0 ;are we indexing too far into the table?
|
|
BLo.S @NoProblem
|
|
BreakError 'Error - Index beyond end of vars list'
|
|
@NoProblem
|
|
ENDIF
|
|
; Debugging
|
|
Lea VarsList(A3,D0),A0 ;point to the previous entry (end of this string).
|
|
Move.W (A0)+,D0 ;get the data offset of the previous entry.
|
|
MoveQ #0,D1 ;clear high word, so unsigned offsets will work.
|
|
Move.W (A0),D1 ;get the offset of this entry.
|
|
Sub.W D1,D0 ;compute the length of this entry.
|
|
Lea 0(A3,D1.L),A0 ;point to the string.
|
|
|
|
Exg A0,A1 ;point A1 to the string, A0 to the output Stream.
|
|
Bsr.S BlockMoveBytes
|
|
Move.L A0,A1 ;get output ptr back.
|
|
Rts
|
|
|
|
;
|
|
; ReuseData - Reuse the data indexed by the encoded byte.
|
|
;
|
|
ReuseData
|
|
Bsr.S FetchData ;fetch the data from the var table.
|
|
Bra UnpackLoop ; go back to the main loop.
|
|
|
|
HandleExtensions
|
|
Move.B (A4)+,D0 ;get the extension opCode.
|
|
Beq.S @JumpTableTrans
|
|
SubQ.B #RunLengthByteTransCode,D0 ; runlength encoding by bytes?
|
|
Blo.S @EntryVectorTrans ; is it an entry vector trans?
|
|
Beq RunLengthByteTrans
|
|
SubQ.B #DiffWordTransCode-RunLengthByteTransCode,D0 ;peel off the next two cases.
|
|
Blo RunLengthWordTrans
|
|
Beq DiffWordTrans
|
|
SubQ.B #DiffEncLongTransCode-DiffWordTransCode,D0 ;peel off the next two cases.
|
|
Blo DiffEncWordTrans
|
|
Beq DiffEncLongTrans
|
|
BreakError 'got an undefined Extension op-code'
|
|
Bra @Return
|
|
|
|
; EntryVector transformation
|
|
; Format is as follows:
|
|
; BranchOffset Delta NumEntries Offset0 < Offset1 Offset2 ... OffsetN >
|
|
; where each item is an encoded value.
|
|
; Offset1...OffsetN is an optional words list that is
|
|
; present only if Delta==0. If Delta != 0 then
|
|
; the Delta is added to Offset0 to create Offset1 etc.
|
|
;
|
|
@EntryVectorTrans
|
|
MoveM.L D2-D7,-(SP)
|
|
|
|
Move.W #$6100,D3
|
|
Move.W #$4EED,D5
|
|
Bsr.S GoGetEncodedValue ;get the initial branch offset.
|
|
Move.W D0,D4
|
|
Bsr.S GoGetEncodedValue ;get the Delta amount.
|
|
Move.W D0,D2
|
|
Bsr.S GoGetEncodedValue ;get the number of entries.
|
|
Move.W D0,D7
|
|
Bsr.S GoGetEncodedValue ;get the inital offset.
|
|
Move.W D0,D6
|
|
Bra.S @HaveOffset
|
|
@ExpandEntryVector
|
|
SubQ #8,D4 ;compute the next branch offset.
|
|
Tst D2 ;is there an offset list?
|
|
Beq.S @GetNextOffset ;if the delta is constant (non-zero) then
|
|
Add.W D2,D6 ; compute next offset.
|
|
Bra.S @HaveOffset
|
|
@GetNextOffset
|
|
Bsr.S GoGetEncodedValue ;get the next offset.
|
|
Move.W D0,D6
|
|
@HaveOffset
|
|
MoveM.W D3-D6,(A1) ;output the next entry vector.
|
|
AddQ #8,A1 ;move the output pointer past the entry.
|
|
DBRA D7,@ExpandEntryVector ;until all entries are done.
|
|
|
|
MoveM.L (SP)+,D2-D7
|
|
Bra.S @Return
|
|
|
|
; JumpTable transformation
|
|
; Format is as follows:
|
|
; Seg# NumEntries Delta0 Delta1 Delta2
|
|
; where each value is encoded.
|
|
;
|
|
@JumpTableTrans
|
|
MoveM.L D3-D7,-(SP)
|
|
|
|
Move.W #$3F3C,D3
|
|
Move.W #$A9F0,D5
|
|
Move.W #6,D6 ;init the offset to our bias.
|
|
Bsr.S GoGetEncodedValue ;get the segment number
|
|
Move.W D0,D4 ;remember seg
|
|
Bsr.S GoGetEncodedValue ;get the number of entries.
|
|
Move.W D0,D7
|
|
Bra.S @skipLastOffset
|
|
@StuffLoop
|
|
Bsr.S GoGetEncodedValue ;get the delta plus bias of 6.
|
|
SubQ #6,D0 ;adjust the delta by my bias (allows some small negs to be a byte).
|
|
Add.W D0,D6 ;add the delta to the last offset.
|
|
MoveM.W D3-D6,(A1) ;output the next jump table entry.
|
|
AddQ #8,A1
|
|
@skipLastOffset
|
|
DBRA D7,@StuffLoop ;until all entries are done.
|
|
MoveM.W D3-D5,(A1) ;output the next jump table entry.
|
|
AddQ #6,A1
|
|
|
|
MoveM.L (SP)+,D3-D7
|
|
@Return
|
|
Rts
|
|
|
|
GoGetEncodedValue
|
|
Bra GetEncodedValue ;get the value
|
|
|
|
RunLengthByteTrans Head
|
|
Bsr.S GoGetEncodedValue ;get the value
|
|
Move.W D0,D1 ;remember value.
|
|
Bsr.S GoGetEncodedValue ;get the rep count.
|
|
@RunLengthByte
|
|
Move.B D1,(A1)+ ;output the value.
|
|
DBRA D0,@RunLengthByte ;loop till all done.
|
|
Tail
|
|
|
|
RunLengthWordTrans Head
|
|
Bsr.S GoGetEncodedValue ;get the value
|
|
Move.W D0,D1 ;remember value.
|
|
Bsr.S GoGetEncodedValue ;get the rep count.
|
|
@RunLengthWord
|
|
Move.W D1,(A1)+ ;output the value.
|
|
DBRA D0,@RunLengthWord ;loop till all done.
|
|
Tail
|
|
|
|
DiffWordTrans Head
|
|
Bsr.S GoGetEncodedValue ;get the initial value
|
|
Move.L D0,D2 ;remember value.
|
|
Bsr.S GoGetEncodedValue ;get the rep count.
|
|
Move.L D0,D1
|
|
Bra.S @FirstTime
|
|
@DiffWord
|
|
Move.B (A4)+,D0 ;get the delta
|
|
Ext.W D0
|
|
Add.W D0,D2 ;add in the signed delta
|
|
@FirstTime
|
|
Move.W D2,(A1)+ ;output the value.
|
|
DBRA D1,@DiffWord ;loop till all done.
|
|
Tail
|
|
|
|
DiffEncWordTrans Head
|
|
Bsr.S GoGetEncodedValue ;get the initial value
|
|
Move.L D0,D2 ;remember value.
|
|
Bsr.S GoGetEncodedValue ;get the rep count.
|
|
Move.L D0,D1
|
|
Bra.S @FirstTime
|
|
@DiffWord
|
|
Bsr.S GoGetEncodedValue ;get the delta.
|
|
Add.L D0,D2 ;add in the signed delta
|
|
@FirstTime
|
|
Move.W D2,(A1)+ ;output the value.
|
|
DBRA D1,@DiffWord ;loop till all done.
|
|
Tail
|
|
|
|
DiffEncLongTrans Head
|
|
Bsr.S GoGetEncodedValue ;get the initial value
|
|
Move.L D0,D2 ;remember value.
|
|
Bsr.S GoGetEncodedValue ;get the rep count.
|
|
Move.L D0,D1
|
|
Bra.S @FirstTime
|
|
@DiffLong
|
|
Bsr.S GoGetEncodedValue ;get the delta.
|
|
Add.L D0,D2 ;add in the signed delta
|
|
@FirstTime
|
|
Move.L D2,(A1)+ ;output the value.
|
|
DBRA D1,@DiffLong ;loop till all done.
|
|
Tail
|