mirror of
https://github.com/aaronsgiles/JPEGView.git
synced 2024-06-11 08:29:29 +00:00
92bdb55672
These are the sources for the final official release of JPEGView for the Mac, back in 1994.
1 line
7.7 KiB
Plaintext
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
|