mirror of
https://github.com/aaronsgiles/JPEGView.git
synced 2024-06-11 23: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.4 KiB
Plaintext
1 line
7.4 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
|
|
subq.w #1,a2 ;Otherwise, pull a byte off the stack
|
|
@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.s @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
|