JPEGView/Source/68020/DecodeRow.a
Aaron Giles 92bdb55672 JPEGView 3.3 for Macintosh
These are the sources for the final official release of JPEGView for the
Mac, back in 1994.
2015-02-05 00:18:10 -08:00

1 line
7.7 KiB
Plaintext

;*********************************************************/
;* This source code copyright (c) 1991-2001, Aaron Giles */
;* See the Read Me file for licensing information. */
;* Contact email: mac@aarongiles.com */
;*********************************************************/
movem.l d3-d7/a2-a4/a6,-(sp) ;//Save all registers
move.l 44(sp),a6 ;//get the address of the CopyData structure in a6
;//(based off stack: 9 registers + 1 a6 link + 1 return addr.
;// = 12 * 4 bytes = 48 bytes)
movem.l store(a6),d1-d7/a0/a2-a4;//Restore some important variables
movea.l dest(a6),a1 ;//Point a1 to the destination
tst.l a1 ;//Are we just initializing?
beq.w @InitTree ;//If so, do it and get outta here
move.w width(a6),d1 ;//Get the width in d1
subq.w #1,d1 ;//Decrement for dbra instruction
@ILoop:
cmpa.l a4,a2 ;//Is the stack empty?
beq.s @NewCode ;//If so, get a new code
move.b -(a2),(a1)+ ;//Otherwise, copy to destination
@EndI:
dbra.w d1,@ILoop ;//Decrement and loop until done
clr.b theReturn(a6) ;//Store false
bra.w @Return ;//Return and exit
;//
;// Get a new code of the appropriate length = (lo)d2
;//
@NewCode:
swap d1 ;//Low word of d1 = byte count
swap d4 ;//Low word of d4 = bits in buffer
@NCLoop:
cmp.w d4,d2 ;//Compare the code size to the buffer size
ble.s @GotCode ;//If there's enough we're done
tst.w d1 ;//Any more bytes available?
bne.s @NCAddByte ;//If so, skip ahead
move.b (a0)+,d1 ;//Get a new byte count
beq.w @ReturnT ;//Return true if zero
@NCAddByte:
subq.w #1,d1 ;//Decrement the byte count
clr.l d0 ;//Clear the accumulator
move.b (a0)+,d0 ;//Get the next byte
lsl.l d4,d0 ;//Shift these new bits over
or.l d0,d3 ;//Or them into the buffer
addq.w #8,d4 ;//Adjust the buffer size
bra.s @NCLoop ;//Loop until we have enough bits
@GotCode:
move.l d3,d0 ;//Copy buffer into accumulator
swap d7 ;//Low word of d7 = (1 << codeSize) - 1
and.w d7,d0 ;//Keep only as many bits as we need
swap d7 ;//Put it back in the high word
lsr.l d2,d3 ;//Shift these bits out of the buffer
sub.w d2,d4 ;//Adjust the bitcount of the buffer
swap d4 ;//Low word of d4 = tree size
swap d1 ;//Low word of d1 = column counter
;//
;// Process the code
;//
cmp.w d5,d0 ;//Clear code?
beq.w @ClrTree ;//If so, reset the LZW tree
swap d5 ;//Low word of d5 = endCode
cmp.w d5,d0 ;//End code?
beq.w @ReturnT ;//If so, return with a true
swap d5 ;//Otherwise put d5 back
;//
;// Handle a normal code
;//
swap d6 ;//Low word of d6 = old
move.w d0,d6 ;//Save a copy of the current code in d6
swap d6 ;//In the high word
cmp.w d4,d0 ;//Is it a valid code?
blt.s @DecLoop ;//If so, continue
bne.w @SignalError ;//If not equal to tree size, then invalid
swap d2 ;//Otherwise, low word of d2 = first
move.b d2,(a2)+ ;//Push that on the stack
swap d2 ;//Restore d2
move.w d6,d0 ;//Current code = last code
@DecLoop:
cmp.w d5,d0 ;//Is the code greater than clear code?
blt.s @DecDone ;//Skip out if so
move.l (0,a3,d0.w*4),d0 ;//Get the parent and code for this node
move.b d0,(a2)+ ;//Push code on the stack
swap d0 ;//Get the parent in the low word
bra.s @DecLoop ;//Loop until we're done
@DecDone:
move.b d0,(a1)+ ;//Send this last guy to the output
swap d2 ;//Low word of d2 = first
move.w d0,d2 ;//Store this for later
swap d2 ;//In the high word
;//
;// Add a new node, if there's room
;//
cmpi.w #4096,d4 ;//Is the tree max'ed out?
bge.w @EndI ;//If so, just loop
swap d0 ;//Swap the current node high
move.w d6,d0 ;//Put last into d0
swap d0 ;//Back to the correct order
swap d6 ;//Set last = old
move.l d0,(0,a3,d4.w*4) ;//Add this to the tree
addq.w #1,d4 ;//Increment the tree size
cmp.w d7,d4 ;//Should we increase the code size?
blt.w @EndI ;//If not, just loop
cmpi.w #12,d2 ;//*Can* we increase the code size?
beq.w @EndI ;//If not, just loop
lsl.l #1,d7 ;//Shift both words of d7 up one bit
ori.l #65536,d7 ;//OR in a new mask bit (65536 == $00010000)
addq.w #1,d2 ;//Increment the code size
bra.w @EndI ;//Loop for some more
;//
;// Initialize the LZW tree
;//
@InitTree:
movea.l src(a6),a0 ;//Get the input address
movea.l tree(a6),a3 ;//Get the tree address
clr.w d0 ;//Clear d0
move.b (a0)+,d0 ;//Get the char size in d0
move.w d0,charSize(a6) ;//Store this elsewhere
movea.l stack(a6),a2 ;//Point a2 to the stack
move.l a2,a4 ;//Copy this into a4
clr.l d1 ;//Erase d1
clr.l d3 ;//Erase d3
moveq.l #1,d4 ;//Set the tree size to 1
lsl.l d0,d4 ;//Shift it left by char size
move.w d4,d5 ;//Copy it to d5 for the end code
addq.w #1,d5 ;//Increment by 1 = end code
swap d5 ;//Put that into the high word
move.w d4,d5 ;//Copy tree size into low word = clear
addq.w #2,d4 ;//tree size += 2
addq.w #1,d0 ;//Increment the char size = code size
move.w d0,d2 ;//Store as the code size
move.l #65537,d7 ;//Put 1's in high & low of d7 (65537 == $00010001)
lsl.l d0,d7 ;//Shift left by code size
subi.l #65536,d7 ;//Decrement the high word by 1 (65536 == $00010000)
bra.s @ReturnT ;//Return a true
;//
;// Reset the LZW tree
;//
@ClrTree:
move.w charSize(a6),d0 ;//Get charSize
move.w #1,d4 ;//Set the tree size to 1
lsl.w d0,d4 ;//Shift it left by charSize
addq.w #2,d4 ;//Tree size += 2
addq.w #1,d0 ;//Increment the char size = code size
move.w d0,d2 ;//Store as the code size
move.l #65537,d7 ;//Put 1's in high & low of d7 (65537 == $00010001)
lsl.l d0,d7 ;//Shift left by code size
subi.l #65536,d7 ;//Decrement the high word by 1 (65536 == $00010000)
;//
;// Get a new code of the appropriate length = (lo)d2
;//
swap d1 ;//Low word of d1 = byte count
swap d4 ;//Low word of d4 = bits in buffer
@CCLoop:
cmp.w d4,d2 ;//Compare the code size to the buffer size
ble.s @CGtCode ;//If there's enough we're done
tst.w d1 ;//Any more bytes available?
bne.s @CCAddByte ;//If so, skip ahead
move.b (a0)+,d1 ;//Get a new byte count
beq.s @ReturnT ;//Return true if zero
@CCAddByte:
subq.w #1,d1 ;//Decrement the byte count
clr.l d0 ;//Clear the accumulator
move.b (a0)+,d0 ;//Get the next byte
lsl.l d4,d0 ;//Shift these new bits over
or.l d0,d3 ;//Or them into the buffer
addq.w #8,d4 ;//Adjust the buffer size
bra.s @CCLoop ;//Loop until we have enough bits
@CGtCode:
move.l d3,d0 ;//Copy buffer into accumulator
swap d7 ;//Low word of d7 = (1 << codeSize) - 1
and.w d7,d0 ;//Keep only as many bits as we need
swap d7 ;//Put it back in the high word
lsr.l d2,d3 ;//Shift these bits out of the buffer
sub.w d2,d4 ;//Adjust the bitcount of the buffer
cmp.w d5,d0 ;//Is it another clear code?
beq.s @CCLoop ;//If so, get another code
swap d4 ;//Low word of d4 = tree size
swap d1 ;//Low word of d1 = column counter
move.b d0,(a1)+ ;//Store this as the output
swap d2 ;//Low word of d2 = first
move.w d0,d2 ;//This code is also first
swap d2 ;//But in the high word
move.w d0,d6 ;//It's also the last
bra.w @EndI ;//Continue on
;//
;// Return to the program
;//
@ReturnT:
move.b #1,theReturn(a6) ;//Store a one
@Return:
move.l theEnd(a6),a1 ;//Get the end of data pointer
cmp.l a0,a1 ;//Did we pass the end of data?
bgt.s @NoError ;//If not, no error
@SignalError:
clr.l theEnd(a6)
@NoError:
movem.l d1-d7/a0/a2-a4,store(a6);//Save some important variables
movem.l (sp)+,d3-d7/a2-a4/a6 ;//Restore all registers