home *** CD-ROM | disk | FTP | other *** search
- ; PhotoCDAGA utility function written by Günther Röhrich
- ; this code is Public Domain and may be used with other programs
-
- ;enhanced 9-Jan-1995 by Günther Röhrich:
-
- ;when the screen is moved around errors at the left side will be much smaller
-
- ; this version is for 68020+ processors only
- ; it is is called from C:
- ; EncodeHAM8(char *rorig, char *gorig, char *borig, char *yham, int xsize);
- ; rorig = original row (red, 8 bit)
- ; gorig = original row (green, 8 bit)
- ; borig = original row (blue, 8 bit)
- ; yham = row in HAM8 chunky format
- ; xsize = size of row in pixels
- ; rstep = step for red component array
- ; gstep = step for green component array
- ; bstep = step for blue component array
-
- MACHINE MC68020
-
- ;NOTE: GCC stores all data as 32 bit at subroutine calls!
-
- rorig EQU 44
- gorig EQU 48
- borig EQU 52
- yham EQU 56 ;pointer to actual row (HAM)
- xsize EQU 60 ;number of pixels (x)
-
-
- XREF _Mult_Table ;address of multiplication table
- XDEF _EncodeHAM8 ;entry point for function
- XREF _ColorCache ;an 256K array
- XREF _ColorTable ;an array with 64 colors
- XREF _rstep
- XREF _gstep
- XREF _bstep
-
- * XDEF _blue_left ;only for debugging purposes
- * XDEF _search_finish ;only for debugging
- * XDEF _MaxError
- * XDEF _MaxErrorPos
- * XDEF _hit ;only for debugging
- * XDEF _t1 ;only for debugging
-
- dseg
-
- cnop 0,4
- _blue_left: dc.b 0 ;this order is better for HAM-encoding
- _red_left: dc.b 0
- _green_left: dc.b 0,0 ;additional dummy-value for faster longword access
-
- cnop 0,2
- _offset_orig: dc.w 0
- _offset_ham: dc.w 0
- _CacheOffset dc.l 0
- rcounter dc.l 0
- gcounter dc.l 0
- bcounter dc.l 0
- _colcount dc.w 2
-
- cseg
-
- ;register usage: D0 = general purpose register
- ; D1 = contains afterwards the error
- ; D2 = orig_blue
- ; D3 = orig_red
- ; D4 = orig_green
- ; D5 = color that should be set
- ; D6 = offset to actual pixel (HAM)
- ; D7 = offset for color table / (0,1,2) at HAM
- ; A0 = best color so far (color+1)*3
- ; A1 = pointer to multiplication table
- ; A2 = pointer to color table / to _blue_left
- ; A3 = smallest error that has been reached so far
- ; A4 = used by the Aztec assembler (small data model)
- ; A5 = not used
- ; A6 = pointer to the actual row (HAM)
-
-
-
- ;computing the difference of color values is done with signed 8 bit
- ;arithmetic
-
- ;the maximum error value is 63^2+63^2+63^2=11907
- ;the summation has to be done therefore with 16 bits
-
-
- ;Initializing
- _EncodeHAM8: movem.l D2-D7/A2-A3/A5/A6,-(A7) ;store registers
- lea _blue_left,A0 ;load start of left colors
- lea _ColorTable,A2
- move.l (A2),(A0) ;initialize left colors
- moveq.l #0,D6 ;initialize ham offset
- move.l yham(sp),A6
- lea _Mult_Table,A1
- lea 255*2(A1),A1
- search_begin: move.l rcounter,D7 ;load position
- move.b ([rorig,sp],D7.L),D3 ;load original red
- lsr.b #2,D3
- add.l _rstep,D7 ;add step
- move.l D7,rcounter ;store position
- move.l gcounter,D7 ;load position
- move.b ([gorig,sp],D7.L),D4 ;load original green
- lsr.b #2,D4
- add.l _gstep,D7 ;add step
- move.l D7,gcounter ;store position
- move.l bcounter,D7 ;load position
- move.b ([borig,sp],D7.L),D2 ;load original blue
- lsr.b #2,D2
- add.l _bstep,D7 ;add step
- move.l D7,bcounter ;store position
- move.w #15000,A3 ;dummy-value for minimum error so far
- lea _ColorTable,A2
- moveq.l #0,D7 ;initialize offset for color table
-
- ;find out if the new pixel has the same color as the previous one
-
- lea _blue_left,A0
- cmp.b (A0),D2
- bne.s search_cont
- cmp.b 1(A0),D3
- bne.s search_cont
- cmp.b 2(A0),D4
- bne.s search_cont
-
- ;the new pixel has the same color, let's do a special encoding
-
- move.w _colcount,D7
- move.b 0(A0,D7.w),D5
- subq.w #1,_colcount
- bpl.s ham6_9
- move.w #2,_colcount
- bra.s ham6_9
-
-
- ;First take a look if we have the value already in the cache
- search_cont: moveq.l #0,D0
- moveq.l #0,D1
- move.b D3,D0 ;compute the cache offset
- lsl.l #6,D0
- or.b D4,D0
- lsl.l #6,D0
- or.b D2,D0 ;now we have the offset in D0
- movea.l _ColorCache,A0 ;load start address of the cache
- move.b 0(A0,D0.l),D1 ;take the value from the cache
- bne _hit ;jump if we have a cache hit
-
- move.l D0,_CacheOffset ;store the offset to avoid recomputing it
- move.l #3,A0 ;dummy-value for best colornumber so far
- ; (3 means color 0)
-
- search_start: bsr _compute_error
- cmp.w D1,A3 ;A3 <= D1 ?
- bls.s search4
- move.w D1,A3 ;D1 is smaller than A3, store it
- move.w D7,A0 ;store color number
- tst.w D1 ;do we have the correct color ?
- beq search5 ;then finish immediately
- search4: cmp.w #64*3,D7 ;have we reached highest colornum ?
- bne.s search_start ;no, then once again
-
- ;A0 contains now (colornumber+1)*3
- ;A3 contains the error for that colornumber
-
- _t1: move.w A0,D0
- movea.l _ColorCache,A2
- move.l _CacheOffset,D1
- move.b D0,0(A2,D1.l) ;store the value in the cache
- lea _blue_left,A2 ;restore A2
-
- ;compute the error when using modify mode
-
- start_ham6: move.b D2,D0 ;load orig_blue
- moveq.l #0,D7 ;assume blue should be changed
- move.b D2,D5 ;store value to change
- sub.b _blue_left,D0 ;D0=D0-_blue_left
- bpl.s ham6_1
- neg.b D0 ;make result positive
- ham6_1: move.b D0,D1 ;store maximum error so far
- move.b D3,D0 ;load orig_red
- sub.b _red_left,D0 ;D0=D0-_red_left
- bpl.s ham6_2
- neg.b D0
- ham6_2: cmp.b D0,D1 ;check D1-D0
- bge.s ham6_3 ;jump if D1>=D0
- move.b D0,D1 ;store new maximum error
- moveq.l #1,D7 ;assume red should be changed
- move.b D3,D5 ;store value to change
- ham6_3: move.b D4,D0 ;load orig_green
- sub.b _green_left,D0 ;D0=D0-_green_left
- bpl.s ham6_4
- neg.b D0
- ham6_4: cmp.b D0,D1
- bge.s ham6_5
- move.b D0,D1 ;store maximum error
- moveq.l #2,D7 ;green should be changed
- move.b D4,D5 ;store value to change
- ham6_5: lea _blue_left,A2
- move.b D5,0(A2,D7.W) ;perform change
-
- ham_error: moveq.l #0,D1
- moveq.l #0,D0
- move.b D2,D0 ;load blue_origin
- sub.b (A2)+,D0 ;D0 = blue_color - blue_origin
- ext.w D0
- add.w 0(A1,D0.W*2),D1
- move.b D3,D0 ;load red_origin
- sub.b (A2)+,D0 ;D0 = red_color - red_origin
- ext.w D0
- add.w 0(A1,D0.W*2),D1
- move.b D4,D0 ;load green_origin
- sub.b (A2)+,D0 ;D0 = green_color - green_origin
- ext.w D0
- add.w 0(A1,D0.W*2),D1
-
- cmpa.w D1,A3 ;check what error is smaller
- bls.s _search_finish ;jump if colortable is better
- ham6_9: add.b #1,D7 ;needed to get correct code
- lsl.b #6,D7 ;HAM8-adjust
- or.b D5,D7
- move.b D7,(A6,D6.W) ;store code in bitmap
-
- addq.w #1,D6 ;increase _offset_ham
- cmp.l xsize(sp),D6 ;end of column ?
- bne search_begin
- bra.s search_end
-
- _search_finish: move.w A0,D0
- lea _ColorTable,A2
- lea -3(A2,D0.W),A3 ;load A3 with pointer to colors
- divu #3,D0
- subq.w #1,D0
- move.b D0,0(A6,D6.W) ;store colornumber in bitmap
- lea _blue_left,A2
- move.l (A3),(A2)
- addq.w #1,D6 ;increase _offset_ham
- cmp.l xsize(sp),D6 ;have we reached the end ?
- bne search_begin
-
- search_end: movem.l (A7)+,D2-D7/A2-A3/A5/A6 ;restore registers
- clr.l rcounter
- clr.l gcounter
- clr.l bcounter
- rts ;jump back to caller
-
-
-
- ;we jump here if we have reached error 0 by colortable only
- ;and there was not a cache hit
- search5: move.w A0,D0
- movea.l _ColorCache,A2
- move.l _CacheOffset,D1
- move.b D0,0(A2,D1.l) ;store the value in the cache
- bra.s _search_finish
-
-
- ;we jump here if we have a cache hit
- ;D1 contains the best color number, but we have to compute the error
-
- _hit: subq.w #3,D1 ;correct color number
- move.w D1,D7
- bsr.s _compute_error
- move.w D1,A3 ;D1 is smaller than A3, store it
- move.w D7,A0 ;store color number
- bra start_ham6 ;continue with HAM encoding
-
-
- ;compute the error
-
- _compute_error: moveq.l #0,D1
- moveq.l #0,D0
- move.b D2,D0 ;load blue_origin
- sub.b 0(A2,D7.W),D0 ;D0 = blue_color - blue_origin
- ext.w D0 ;extend result to word
- add.w 0(A1,D0.W*2),D1
- addq.w #1,D7 ;advance color table offset
- move.b D3,D0 ;load red_origin
- sub.b 0(A2,D7.W),D0 ;D0 = red_color - red_origin
- ext.w D0
- add.w 0(A1,D0.W*2),D1
- addq.w #1,D7 ;advance color table offset
- move.b D4,D0 ;load green_origin
- sub.b 0(A2,D7.W),D0 ;D0 = green_color - green_origin
- ext.w D0
- add.w 0(A1,D0.W*2),D1 ;D1 = D1 + D0*D0
- addq.w #1,D7 ;advance color table offset
- rts
-
-
-
-
-