home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Kosovo Orphans' Appeal Charity CD
/
KosovoOrphansAppeal.iso
/
archimedesworld_cd2
/
acornanswers
/
_scape2
/
s
/
dith
next >
Wrap
Text File
|
1996-01-23
|
18KB
|
424 lines
; g256wnp_internal
; a leaf APCS function
; to dither from source to destination sprite
;
; C prototype
; void g256wnp_internal(int x, int y, char *dp, char *sp, compact_dither_error *de, char *lut, unsigned int *pal256def)
; x is sprite width in pixels, y is height in pixels,
; dp pts to destination sprite image (8bpp),
; sp pts to source image (32bpp),
; de pts to line buffer to hold compact_dither_errors (each of form er,eg,eb,byte-to-pad - all signed chars),
; lut pts to 32768 byte look up table to map 15 bit rbg colour to nearest available colour number in default palette,
; pal256def pts to 256 int list of default palette
;
^ 4, fp
dxp # 4
dyp # 4
ddp # 4
dsp # 4
dde # 4
dlut # 4
dpal256def # 4
gwi_xp RN r0
gwi_yp RN r1 ;nb also is gwi_m4
gwi_m4 RN r1 ;nb also is gwi_yp
gwi_dp RN r2
gwi_sp RN r3
gwi_de RN r4
gwi_lut RN r5
gwi_pal256def RN r6
gwi_r RN r7
gwi_g RN r8
gwi_b RN r9
gwi_i RN r10
gwi_m3 RN r11 ;nb also is fp
gwi_m2 RN r12
gwi_m1 RN r13
gwi_lde RN r14
ASSERT gwi_m1>gwi_m2 :LAND: gwi_m2>gwi_m3 :LAND: gwi_m3>gwi_m4
;Note, scanning of image is done in a serpentine fashion to reduce dither
;pattern effects, & to maintain speed the main processing code is replicated,
MACRO ;more or less, three times: 1st to scan the top row (for which we have no
$label gwi_seg1 ;precalculated errors from a row above), & then twice more, once to scan odd
;rows right to left & once for scanning even rows left to right.
;This macro contains code common to each of the three incidents - it is
;entered with gwi_r, _g & _b containing the desired destination colour
;(including any error terms added in), & it writes to destination image the
;nearest colour available, then calculates the error term for this pixel in
;gwi_lde (last dither error).
$label MOV gwi_m1, gwi_r, ASR #3 ;from here . . .
CMP gwi_r, #255
MOVGT gwi_m1, #31
CMP gwi_r, #0
MOVLT gwi_m1, #0 ;to here, round r component down to 5 bits & clip to 0-31 (into _m1 bits 0-4)
MOV gwi_m2, gwi_g, ASR #3
CMP gwi_g, #255
MOVGT gwi_m2, #31
CMP gwi_g, #0
MOVLT gwi_m2, #0
ADD gwi_m1, gwi_m1, gwi_m2, ASL #5 ;as above, for g component, into _m1 bits 5-9
MOV gwi_m2, gwi_b, ASR #3
CMP gwi_b, #255
MOVGT gwi_m2, #31
CMP gwi_b, #0
MOVLT gwi_m2, #0
ADD gwi_m1, gwi_m1, gwi_m2, ASL #10 ;as above, for b component, into _m1 bits 10-14
;ie _m1 is now the desired 15 bits rgb colour
LDRB gwi_m1, [gwi_lut, gwi_m1] ;set _m1 to number of nearest available colour via a look up table
STRB gwi_m1, [gwi_dp, #0] ;write this to destination image
LDR gwi_m1, [gwi_pal256def, gwi_m1, ASL #2] ;read the 24 bit rgb value of the colour just written
MOV gwi_m2, gwi_m1, LSL #16 ;from here . . .
SUB gwi_m3, gwi_r, gwi_m2, LSR #24
CMP gwi_m3, #127
MOVGT gwi_m3, #127
CMP gwi_m3, #-127
MOVLT gwi_m3, #-127
AND gwi_m3, gwi_m3, #255 ;to here, calc (desired red)-(used red), & clip to a signed 8 bit value
MOV gwi_m2, gwi_m1, LSL #8
SUB gwi_m2, gwi_g, gwi_m2, LSR #24
CMP gwi_m2, #127
MOVGT gwi_m2, #127
CMP gwi_m2, #-127
MOVLT gwi_m2, #-127
AND gwi_m2, gwi_m2, #255
ADD gwi_m3, gwi_m3, gwi_m2, LSL #8 ;as above, for green, inserting the error into correct bits in _m3
SUB gwi_m2, gwi_b, gwi_m1, LSR #24
CMP gwi_m2, #127
MOVGT gwi_m2, #127
CMP gwi_m2, #-127
MOVLT gwi_m2, #-127
AND gwi_m2, gwi_m2, #255
ADD gwi_lde, gwi_m3, gwi_m2, LSL #16 ;as above, for blue - _lde now holds all three signed
;8 bit error terms
MEND
gwi_asl DCD 0 ;storage for sl, fp & sp, during internal calcs
gwi_afp DCD 0
gwi_asp DCD 0
gwi_aj DCD 0 ;current row number
EXPORT g256wnp_internal
gwinsta DCB "g256wnp_internal", 0
ALIGN
gwinend DCD &ff000000 + gwinend - gwinsta
g256wnp_internal
MOV ip, sp
STMFD sp!, {a1-a4} ;stack fn args x,y,dp & sp onto stack below remaining args de,lut & pal256def
STMFD sp!, {r4-r9, fp, ip, lr, pc}
SUB fp, ip, #20 ;leaf fn & little need of stack, so don't bother with stack checking
STR sl, gwi_asl
STR fp, gwi_afp
STR sp, gwi_asp ; strictly, don't need to save this, as restore frame from fp which
; contains old sp, however keep it here in case change code st need
; to make an external APCS call
;set up regs now
LDR gwi_xp, dxp ;note dxp etc are register relative - so this actually does LDR _xp, [fp, #4]
LDR gwi_yp, dyp ;sprite heights in pixels (xp is corresponding widths)
LDR gwi_dp, ddp ;ptr to destination sprite image (ie image data itself & not the spr hdr)
LDR gwi_sp, dsp ;ptr to source sprite image
LDR gwi_de, dde ;ptr to a buffer for error terms (must be xp words long)
LDR gwi_lut, dlut ;ptr to lut to map 15bit rgb colour to nearest available in default 8bpp pal
LDR gwi_pal256def, dpal256def ;ptr to default 8bpp 256 entry palette (used to calc errors)
;code
MOV gwi_i, gwi_xp ;current column number (actually, xp-number)
CMP gwi_i, #0
BLE gwi_xloop1done
gwi_xloop1
LDR gwi_m1, [gwi_sp, #0]
AND gwi_r, gwi_m1, #255 ;from here . . .
MOV gwi_g, gwi_m1, LSR #8
AND gwi_g, gwi_g, #255
MOV gwi_b, gwi_m1, LSR #16
AND gwi_b, gwi_b, #255 ;to here, extract three r,g & b 8 bit components into _r, _g & _b
CMP gwi_i, gwi_xp
BEQ gwi_xl1_b1
;if not on first pixel in row, there is an error term to add in from left:
MOV gwi_m1, gwi_lde, LSL #24 ;extract red error from _lde &
MOV gwi_m1, gwi_m1, ASR #24 ;sign extend it to 32 bits
RSBS gwi_m1, gwi_m1, gwi_m1, ASL #3 ;from here . . .
ADDMI gwi_m1, gwi_m1, #15 ; (need to ensure *7/16 will round towards 0, rather than down)
ADD gwi_r, gwi_r, gwi_m1, ASR #4 ;to here, add to _r 7/16 lde red error term
MOV gwi_m1, gwi_lde, LSL #16 ;from here . . .
MOV gwi_m1, gwi_m1, ASR #24
RSBS gwi_m1, gwi_m1, gwi_m1, ASL #3
ADDMI gwi_m1, gwi_m1, #15
ADD gwi_g, gwi_g, gwi_m1, ASR #4 ;to here, extract green error & add 7/16 of it into _g
MOV gwi_m1, gwi_lde, LSL #8 ;from here . . .
MOV gwi_m1, gwi_m1, ASR #24
RSBS gwi_m1, gwi_m1, gwi_m1, ASL #3
ADDMI gwi_m1, gwi_m1, #15
ADD gwi_b, gwi_b, gwi_m1, ASR #4 ;to here, extract blue error from lde & add 7/16 into _b
STR gwi_lde, [gwi_de, gwi_i, ASL #2] ;buffer lde for when processing row below
gwi_xl1_b1
gwi_seg1 ;write to destination image & calculate error for this pixel (into lde)
ADD gwi_dp, gwi_dp, #1 ;step through destination image one pixel
ADD gwi_sp, gwi_sp, #4 ;step through source image one pixel
SUBS gwi_i, gwi_i, #1
BGT gwi_xloop1 ;& repeat till all of first row processed
gwi_xloop1done
;now step down to next row (remember, serpentine scanning)
RSB gwi_m2, gwi_xp, #4
AND gwi_m1, gwi_m2, #3 ; . . . to get past righthand wastage of last row, dest image
ADD gwi_m1, gwi_m1, gwi_xp ; . . . to get past end of next row
SUB gwi_m1, gwi_m1, #1 ; . . . to get back to last pixel on that row
ADD gwi_dp, gwi_dp, gwi_m1 ;make the adjustment to _dp
ADD gwi_sp, gwi_sp, gwi_xp, LSL #2 ;from here . . .
SUB gwi_sp, gwi_sp, #4 ;to here, as above for src image (note, it has 4*xp bytes per row)
SUBS gwi_m1, gwi_yp, #2
BMI gwi_yloopdone ;carry on with next row, unless all rows done (note, subtract
STR gwi_m1, gwi_aj ; 2 from yp initially since yp is # rows counting from 1, &
; branch cond is MI, ie loop counts rows including 0)
;note, de buffer holds errors for row above, running from right in low
;memory to left side in high mem. Next row will be scanned right to
gwi_yloop ;left, so need extract errors from buffer in increasing memory order.
STR gwi_lde, [gwi_de, #0] ;buffer error for final pixel from last row
MOV gwi_i, #1
CMP gwi_i, gwi_xp
BGT gwi_xloop2done
;all remaining code is similar to preceeding, except have to add in
gwi_xloop2 ;errors from row above, & scan row in reverse direction
LDR gwi_m1, [gwi_sp, #0]
AND gwi_r, gwi_m1, #255 ;from here . . .
MOV gwi_g, gwi_m1, LSR #8
AND gwi_g, gwi_g, #255
MOV gwi_b, gwi_m1, LSR #16
AND gwi_b, gwi_b, #255 ;to here, extract three r,g & b 8 bit components into _r, _g & _b
SUB gwi_m4, gwi_i, #1 ;from here . . .
LDR gwi_m4, [gwi_de, gwi_m4, ASL #2]
MOV gwi_m1, gwi_m4, LSL #24
MOV gwi_m1, gwi_m1, ASR #24
ADDS gwi_m1, gwi_m1, gwi_m1, ASL #2
ADDMI gwi_m1, gwi_m1, #15
ADD gwi_r, gwi_r, gwi_m1, ASR #4
MOV gwi_m1, gwi_m4, LSL #16
MOV gwi_m1, gwi_m1, ASR #24
ADDS gwi_m1, gwi_m1, gwi_m1, ASL #2
ADDMI gwi_m1, gwi_m1, #15
ADD gwi_g, gwi_g, gwi_m1, ASR #4
MOV gwi_m1, gwi_m4, LSL #8
MOV gwi_m1, gwi_m1, ASR #24
ADDS gwi_m1, gwi_m1, gwi_m1, ASL #2
ADDMI gwi_m1, gwi_m1, #15
ADD gwi_b, gwi_b, gwi_m1, ASR #4 ;to here, add in 5/16 error for pixel above
CMP gwi_i, #1
BEQ gwi_xl2_b1
SUB gwi_m2, gwi_i, #2 ;similiarly (if not on rightmost column) . . .
LDR gwi_m4, [gwi_de, gwi_m2, ASL #2]
MOV gwi_m1, gwi_m4, LSL #24
MOVS gwi_m1, gwi_m1, ASR #24
ADDMI gwi_m1, gwi_m1, #15
ADD gwi_r, gwi_r, gwi_m1, ASR #4
MOV gwi_m1, gwi_m4, LSL #16
MOVS gwi_m1, gwi_m1, ASR #24
ADDMI gwi_m1, gwi_m1, #15
ADD gwi_g, gwi_g, gwi_m1, ASR #4
MOV gwi_m1, gwi_m4, LSL #8
MOVS gwi_m1, gwi_m1, ASR #24
ADDMI gwi_m1, gwi_m1, #15
ADD gwi_b, gwi_b, gwi_m1, ASR #4 ;add in 1/16 error for pixel to above right
STR gwi_lde, [gwi_de, gwi_m2, ASL #2] ;can now safely overwrite value in buffer with lde for next row
MOV gwi_m1, gwi_lde, LSL #24
MOV gwi_m1, gwi_m1, ASR #24
RSBS gwi_m1, gwi_m1, gwi_m1, ASL #3
ADDMI gwi_m1, gwi_m1, #15
ADD gwi_r, gwi_r, gwi_m1, ASR #4
MOV gwi_m1, gwi_lde, LSL #16
MOV gwi_m1, gwi_m1, ASR #24
RSBS gwi_m1, gwi_m1, gwi_m1, ASL #3
ADDMI gwi_m1, gwi_m1, #15
ADD gwi_g, gwi_g, gwi_m1, ASR #4
MOV gwi_m1, gwi_lde, LSL #8
MOV gwi_m1, gwi_m1, ASR #24
RSBS gwi_m1, gwi_m1, gwi_m1, ASL #3
ADDMI gwi_m1, gwi_m1, #15
ADD gwi_b, gwi_b, gwi_m1, ASR #4 ;now add in 7/16 error for pixel to right
gwi_xl2_b1
CMP gwi_i, gwi_xp
BEQ gwi_xl2_b2
LDR gwi_m4, [gwi_de, gwi_i, ASL #2] ;if not on far left column . . .
MOV gwi_m1, gwi_m4, LSL #24
MOV gwi_m1, gwi_m1, ASR #24
ADDS gwi_m1, gwi_m1, gwi_m1, ASL #1
ADDMI gwi_m1, gwi_m1, #15
ADD gwi_r, gwi_r, gwi_m1, ASR #4
MOV gwi_m1, gwi_m4, LSL #16
MOV gwi_m1, gwi_m1, ASR #24
ADDS gwi_m1, gwi_m1, gwi_m1, ASL #1
ADDMI gwi_m1, gwi_m1, #15
ADD gwi_g, gwi_g, gwi_m1, ASR #4
MOV gwi_m1, gwi_m4, LSL #8
MOV gwi_m1, gwi_m1, ASR #24
ADDS gwi_m1, gwi_m1, gwi_m1, ASL #1
ADDMI gwi_m1, gwi_m1, #15
ADD gwi_b, gwi_b, gwi_m1, ASR #4 ;add in 3/16 error for pixel to above left
gwi_xl2_b2
gwi_seg1 ;write destination pixel & calc new error for pixel
SUB gwi_dp, gwi_dp, #1
SUB gwi_sp, gwi_sp, #4
ADD gwi_i, gwi_i, #1
CMP gwi_i, gwi_xp
BLE gwi_xloop2 ;loop back til all of right to left row processed
gwi_xloop2done
RSB gwi_m2, gwi_xp, #4
AND gwi_m1, gwi_m2, #3
ADD gwi_m1, gwi_m1, gwi_xp
ADD gwi_m1, gwi_m1, #1
ADD gwi_dp, gwi_dp, gwi_m1
ADD gwi_sp, gwi_sp, gwi_xp, LSL #2
ADD gwi_sp, gwi_sp, #4 ;step sp, dp to next row (to be scanned left to right)
LDR gwi_m1, gwi_aj
SUBS gwi_m1, gwi_m1, #1
STR gwi_m1, gwi_aj
BMI gwi_yloopdone ;continue with next row, unless all done
SUB gwi_m1, gwi_xp, #1
STR gwi_lde, [gwi_de, gwi_m1, ASL #2] ;buffer error for final pixel on last row
MOV gwi_i, gwi_xp
CMP gwi_i, #0
BLE gwi_xloop3done
gwi_xloop3
LDR gwi_m1, [gwi_sp, #0]
AND gwi_r, gwi_m1, #255 ;from here . . .
MOV gwi_g, gwi_m1, LSR #8
AND gwi_g, gwi_g, #255
MOV gwi_b, gwi_m1, LSR #16
AND gwi_b, gwi_b, #255 ;to here, extract three r,g & b 8 bit components into _r, _g & _b
SUB gwi_m4, gwi_i, #1 ;for pixel above . . .
LDR gwi_m4, [gwi_de, gwi_m4, ASL #2]
MOV gwi_m1, gwi_m4, LSL #24
MOV gwi_m1, gwi_m1, ASR #24
ADDS gwi_m1, gwi_m1, gwi_m1, ASL #2
ADDMI gwi_m1, gwi_m1, #15
ADD gwi_r, gwi_r, gwi_m1, ASR #4
MOV gwi_m1, gwi_m4, LSL #16
MOV gwi_m1, gwi_m1, ASR #24
ADDS gwi_m1, gwi_m1, gwi_m1, ASL #2
ADDMI gwi_m1, gwi_m1, #15
ADD gwi_g, gwi_g, gwi_m1, ASR #4
MOV gwi_m1, gwi_m4, LSL #8
MOV gwi_m1, gwi_m1, ASR #24
ADDS gwi_m1, gwi_m1, gwi_m1, ASL #2
ADDMI gwi_m1, gwi_m1, #15
ADD gwi_b, gwi_b, gwi_m1, ASR #4 ;add in 5/16 error
CMP gwi_i, gwi_xp
BEQ gwi_xl3_b1
;if not on leftmost column . . .
LDR gwi_m4, [gwi_de, gwi_i, ASL #2]
MOV gwi_m1, gwi_m4, LSL #24
MOVS gwi_m1, gwi_m1, ASR #24
ADDMI gwi_m1, gwi_m1, #15
ADD gwi_r, gwi_r, gwi_m1, ASR #4
MOV gwi_m1, gwi_m4, LSL #16
MOVS gwi_m1, gwi_m1, ASR #24
ADDMI gwi_m1, gwi_m1, #15
ADD gwi_g, gwi_g, gwi_m1, ASR #4
MOV gwi_m1, gwi_m4, LSL #8
MOVS gwi_m1, gwi_m1, ASR #24
ADDMI gwi_m1, gwi_m1, #15
ADD gwi_b, gwi_b, gwi_m1, ASR #4 ;add in 1/16 error for pixel to above left
STR gwi_lde, [gwi_de, gwi_i, ASL #2] ;buffer last error
MOV gwi_m1, gwi_lde, LSL #24
MOV gwi_m1, gwi_m1, ASR #24
RSBS gwi_m1, gwi_m1, gwi_m1, ASL #3
ADDMI gwi_m1, gwi_m1, #15
ADD gwi_r, gwi_r, gwi_m1, ASR #4
MOV gwi_m1, gwi_lde, LSL #16
MOV gwi_m1, gwi_m1, ASR #24
RSBS gwi_m1, gwi_m1, gwi_m1, ASL #3
ADDMI gwi_m1, gwi_m1, #15
ADD gwi_g, gwi_g, gwi_m1, ASR #4
MOV gwi_m1, gwi_lde, LSL #8
MOV gwi_m1, gwi_m1, ASR #24
RSBS gwi_m1, gwi_m1, gwi_m1, ASL #3
ADDMI gwi_m1, gwi_m1, #15
ADD gwi_b, gwi_b, gwi_m1, ASR #4 ;& add in 7/16 error for pixel to left
gwi_xl3_b1
CMP gwi_i, #1
BEQ gwi_xl3_b2
;if not on far right . . .
SUB gwi_m2, gwi_i, #2
LDR gwi_m4, [gwi_de, gwi_m2, ASL #2]
MOV gwi_m1, gwi_m4, LSL #24
MOV gwi_m1, gwi_m1, ASR #24
ADDS gwi_m1, gwi_m1, gwi_m1, ASL #1
ADDMI gwi_m1, gwi_m1, #15
ADD gwi_r, gwi_r, gwi_m1, ASR #4
MOV gwi_m1, gwi_m4, LSL #16
MOV gwi_m1, gwi_m1, ASR #24
ADDS gwi_m1, gwi_m1, gwi_m1, ASL #1
ADDMI gwi_m1, gwi_m1, #15
ADD gwi_g, gwi_g, gwi_m1, ASR #4
MOV gwi_m1, gwi_m4, LSL #8
MOV gwi_m1, gwi_m1, ASR #24
ADDS gwi_m1, gwi_m1, gwi_m1, ASL #1
ADDMI gwi_m1, gwi_m1, #15
ADD gwi_b, gwi_b, gwi_m1, ASR #4 ;add in 3/16 error for pixel to above right
gwi_xl3_b2
gwi_seg1 ;write destination pixel & calc its error
ADD gwi_dp, gwi_dp, #1
ADD gwi_sp, gwi_sp, #4
SUBS gwi_i, gwi_i, #1
BGT gwi_xloop3 ;continue till all of left to right row processed
gwi_xloop3done
RSB gwi_m2, gwi_xp, #4
AND gwi_m1, gwi_m2, #3
ADD gwi_m1, gwi_m1, gwi_xp
SUB gwi_m1, gwi_m1, #1
ADD gwi_dp, gwi_dp, gwi_m1
ADD gwi_sp, gwi_sp, gwi_xp, LSL #2
SUB gwi_sp, gwi_sp, #4 ;step dp, sp to start of next right-to-left row
LDR gwi_m1, gwi_aj
SUBS gwi_m1, gwi_m1, #1
STR gwi_m1, gwi_aj
BPL gwi_yloop ;& repeat, until all rows done
gwi_yloopdone
;all done
LDR sp, gwi_asp
LDR fp, gwi_afp
LDR sl, gwi_asl
LDMEA fp, {r4-r9, fp, sp, pc}^ ;get out of here!
END