home *** CD-ROM | disk | FTP | other *** search
RISC OS BBC BASIC V Source | 1994-02-08 | 14.4 KB | 425 lines |
- >TestDither
- : Cy Booker
- : 86 Church View
- : Main Road
- : Crockenhill
- : Swanley
- : Kent
- : BR8 8 JW
- run this in a 16 colour Wimp mode with default palette
- the bottom half uses an accurate 2x2 dither algorithm
- the top half uses ColourTrans
- if change parameters to xdither_rgb then works in any mode/palette (upto 8bpp)
- the suprising fact is that for 4bpp it looks as though we have changed
- the working resolution from 0..255 to 0..65536 (extra 2.4 decimal places)
- only doubles the "resolution"
- all sub-routines conform to
- parameters in R0, R1, R2, ...
- returns in R0, R1, R2, ... [F0, F1, F2, ...]
- corrupts R0-R3, ip, lr
- preserves R4-R9, sl, gb, sp
- if name has `x' prefix then
- PSR_V set on SWI error, PSR_NZC undefined
- PSR_V clear if OK, PRS_NZC preserved
- else if name has `v' prefix then
- PSR_Z is state of R0, PSR_NCV preserved
- else PSR_NZCV preserved
- $+ " ["+
- )+ "]"
- sp = 13
- lr = 14
- !3 gb = 12 :
- not APCS !!!
- "3 ip = 11 :
- not APCS !!!
- PSR_V = &10000000
- L% = 10240
- code% L% : L% += code%
- pass%= %1000
- %1010
- O% = 0 : P% = code%
- [OPT pass%
-
- udivide_255
-
- udivide_3
-
- udivmod
-
- xdither_rgb
- .(
- convert_paletteentry_to_rgb
- /(
- convert_rgb_to_paletteentry
- 0E.Palette ; standard 16-colour wimp palette
- EQUD &FFFFFF00
- EQUD &DDDDDD00
- EQUD &BBBBBB00
- EQUD &99999900
- EQUD &77777700
- EQUD &55555500
- EQUD &33333300
- EQUD &00000000
- EQUD &99440000
- EQUD &00EEEE00
- EQUD &00CC0000
- EQUD &0000DD00
- EQUD &BBEEEE00
- EQUD &00885500
- EQUD &00BBFF00
- EQUD &FFBB0000
- .xdither
- STMFD (sp)!, {lr}
- MOV R3, #20
- ADR R4, Palette
- MOV R5, #4
- BL xdither_rgb
- LDMvsFD (sp)!, {pc}
- H" STMFD (sp)!, {R0-R3}
- I" STMFD (sp)!, {R0-R3}
- MOV R0, #1 << 5
- MOV R1, sp
- L# SWI "XOS_SetColour"
- M" ADD sp, sp, #4*4*2
- LDMFD (sp)!, {pc}
- O ]
- pass%
- s(2), e(2), c(2)
- s() = 0.03, 0.80, 0.42
- e() = 0.94, 0.05, 0.79
- i%= 0
- s(i%) =
- e(i%) = 1 - (
- (1) < 0.7
- X
- nstep = 512
- i= 0
- 1.00
- 1/nstep
- c() = e()-s()
- c() = i*c()
- c() = c() + s()
- A% = c(0)*&10000 + 0.5
- B% = c(1)*&10000 + 0.5
- C% = c(2)*&10000 + 0.5
- xdither
- c(
- i*1024, 0, 1024/nstep, 512
- A% = c(0)*&ff + 0.5
- B% = c(1)*&ff + 0.5
- C% = c(2)*&ff + 0.5
- gD
- "ColourTrans_SetGCOL", (A%<<8)+(B%<<16)+(C%<<24),,,&100,0
- h,
- i*1024, 512, 1024/nstep, 512
- *ScreenSave <d>.Tmp.screen
- link(a$):
- udivide_3
- [OPT pass%
- qS; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- r*; Calculates round(n/3) extremely fast
- ; In R0 = n
- ; Out R0 = round(n
- .udivide_3
- x' MOV R2, R0, LSR #32 - 2
- y& ADDS R1, R0, R0, LSL #2
- zD ADDcs R2, R2, #1 ; R2.R1 = R0 * &00000005
- {' ADD R2, R2, R2, LSL #16
- |' ADDS R3, R1, R1, LSL #16
- }D ADC R2, R2, R1, LSR #32 - 16; R2.R3 = R0 * &00050005
- ~& ADD R2, R2, R2, LSL #8
- & ADDS R1, R3, R3, LSL #8
- D ADC R2, R2, R3, LSR #32 - 8 ; R2.R1 = R0 * &05050505
- & ADD R2, R2, R2, LSL #4
- & ADDS R3, R1, R1, LSL #4
- D ADC R0, R2, R1, LSR #32 - 4 ; R0.R3 = R0 * &55555555
- 6 ADDmi R0, R0, #1 ; round up
- MOVS pc, lr
- ]:= 0
- udivide_255
- [OPT pass%
- S; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ,; Calculates round(n/255) extremely fast
- ; In R0 = n
- ; Out R0 = round(n
- 255)
- .udivide_255
- ' MOV R2, R0, LSR #32 - 8
- & ADDS R1, R0, R0, LSL #8
- D ADDcs R2, R2, #1 ; R2.R1 = R0 * &00000101
- ' ADD R2, R2, R2, LSL #16
- ' ADDS R3, R1, R1, LSL #16
- D ADC R0, R2, R1, LSR #32 - 16; R0.R3 = R0 * &01010101
- 6 ADDmi R0, R0, #1 ; round up
- MOVS pc, lr
- ]:= 0
- udivmod
- [OPT pass%
- R;~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
- ; In R0 = unsigned
- #; R1 = unsigned, non-zero
- 4; Out R0 = R0 / R1 (rounded down towards zero)
- ; R1 = R0
- 6; Note if R1 = 0 then get stuck in infinite loop!
- .udivmod
-
- divrem(2, 0, 1, 3)
- MOV R1, R0
- MOV R0, R2
- MOVS pc, lr
- ]:= 0
- xdither_rgb
- L_TopLeft, L_BottomRight, L_TopRight, L_Mode, L_BPP
- loop
- first 3 words are accumulator (ie tl, tl+br, tl+br+tr)
- L_TopLeft = 3 << 2
- L_BottomRight = 4 << 2
- L_TopRight = 5 << 2
- 7 L_Mode = 6 << 2 :
- implicit
- 7 L_BPP = 7 << 2 :
- implicit
- link("convert_paletteentry_to_rgb,convert_rgb_to_paletteentry,udivide_3")
- [OPT pass%
- S; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- R; Calculate a 2x2 dither pattern for an rgb given a mode and a palette pointer
- M; This routine needed since cant change palette when redirected output to
- ; sprite
- .; The algorithm based on colourtrans's, ie
- ; tl = closest
- O; br = 2.actual - tl = actual - (tl - actual) = actual - diff
- ; tr = 2.actual - (tl+br)/2
- %; bl = 2.actual - (tl+br+tr) / 3
- ; In R0 = &000r.rrrr
- ; R1 = &000g.gggg
- ; R2 = &000b.bbbb
- ; R3 = mode
- /; R4 = pointer to colourtrans palette
- +; R5 = bpp for mode {2, 4, 8, 16}
- 8; Out R0 = top row of screen bytes (word expanded)
- ;; R1 = bottom row of screen bytes (word expanded)
- ; R2 = R0
- ; R3 = R1
- .xdither_rgb
- : STMFD (sp)!, {R0, R1, R2, R3, R5, R6-R9, lr}
- J LDMIA (sp)!, {R6, R7, R8} ; R6/R7/R8= rgb wanted
- # SUB sp, sp, #L_Mode
- / BL convert_rgb_to_paletteentry
- % LDR R1, [sp, #L_Mode]
- MOV R2, R4
- < SWI "XColourTrans_ReturnColourNumberForMode"
- $ Bvs error_dither_rgb
- ( STR R0, [sp, #L_TopLeft]
- ;
- ( LDR R0, [R4, R0, LSL #2]
- / BL convert_paletteentry_to_rgb
- B STMIA sp, {R0, R1, R2} ; Stack tl rgb
- A
- aux_dithers_rgb ; br = 2x - tl
- , STR R0, [sp, #L_BottomRight]
- ;
- ( LDR R0, [R4, R0, LSL #2]
- / BL convert_paletteentry_to_rgb
- $ LDMIA sp, {R3, ip, lr}
- ADD R0, R0, R3
- ADD R1, R1, ip
- ADD R2, R2, lr
- E STMIA sp, {R0, R1, R2} ; Stack tl+br rgb
- " MOVS R0, R0, ASR #1
- K ADDcs R0, R0, #1 ; ensure lsb is correct
- " MOVS R1, R1, ASR #1
- ADDcs R1, R1, #1
- " MOVS R2, R2, ASR #1
- ADDcs R2, R2, #1
- J
- aux_dithers_rgb ; tr = 2x - (tl + br)/2
- ) STR R0, [sp, #L_TopRight]
- ;
- ( LDR R0, [R4, R0, LSL #2]
- / BL convert_paletteentry_to_rgb
- $ LDMIA sp, {R3, ip, lr}
- H ADD R5, R0, R3 ; R5 = red(tl+br+tr)
- J ADD R9, R1, ip ; R9 = green(tl+br+tr)
- 4 ADD R0, R2, lr
- Q BL udivide_3 ; this ensures lsb is correct
- N STR R0, [sp, #8] ; stack blue(tl+br+tr) / 3
- MOV R0, R9
- BL udivide_3
- O STR R0, [sp, #4] ; stack green(tl+br+tr) / 3
- MOV R0, R5
- BL udivide_3
- LDMIB sp, {R1, R2}
- K
- aux_dithers_rgb ; bl = 2x - (tl+br+tr)/3
- $ LDR R5, [sp, #L_BPP]
- , LDR R2, [sp, #L_BottomRight]
- ) LDR R3, [sp, #L_TopRight]
- ( LDR R4, [sp, #L_TopLeft]
- C
- R R1, R2, R0, LSL R5 ; R1= bottom row
- @
- R R0, R3, R4, LSL R5 ; R0= top row
- .loop ADD R5, R5, R5
- CMP R5, #16
- K
- Rls R0, R0, R0, LSL R5 ; Expand into full words
- %
- Rls R1, R1, R1, LSL R5
- Blo loop
- MOV R2, R0
- MOV R3, R1
- A CMP pc, #0 ; clear psr_v
- .error_dither_rgb
- ' ADD sp, sp, #L_Mode + 4
- & LDMFD (sp)!, {R5-R9, pc}
- ]:= 0
- aux_dithers_rgb
- [OPT pass%
- H RSB R0, R0, R6, LSL #1 ; red = 2*x - f(red)
- & RSB R1, R1, R7, LSL #1
- & RSB R2, R2, R8, LSL #1
- H CMP R0, #&10000 ; check for overflow
- D MOVhi R0, #0 ; and underflow!
- MOVgt R0, #&10000
- CMP R1, #&10000
- MOVhi R1, #0
- MOVgt R1, #&10000
- CMP R2, #&10000
- MOVhi R2, #0
- MOVgt R2, #&10000
- / BL convert_rgb_to_paletteentry
- % LDR R1, [sp, #L_Mode]
- MOV R2, R4
- < SWI "XColourTrans_ReturnColourNumberForMode"
- !$ Bvs error_dither_rgb
- " ]:= 0
- xconvert_cmyk_to_rgb
- [OPT pass%
- &R; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ; In R0 = &000c.cccc
- ; R1 = &000y.yyyy
- ; R2 = &000m.mmmm
- ; R3 = &000k.kkkk
- ; Out R0 = &000r.rrrr
- ; R1 = &000g.gggg
- ; R2 = &000b.bbbb
- .xconvert_cmyk_to_rgb
- 13 SWI "XColourTrans_ConvertCMYKToRGB"
- MOV pc, lr
- 3 ]:= 0
- xconvert_hsv_to_rgb
- [OPT pass%
- 7R; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- 91; In R0 = &0hhh.hhhh (or -1 if achromatic)
- ; R1 = &000s.ssss
- ; R2 = &000v.vvvv
- ; Out R0 = &000r.rrrr
- ; R1 = &000g.gggg
- ; R2 = &000b.bbbb
- .xconvert_hsv_to_rgb
- AP CMN R0, #+1 ; Achromatic ? [clear PSR_V]
- MOVeq R0, R2
- MOVeq R1, R2
- D2 SWIne "XColourTrans_ConvertHSVToRGB"
- MOV pc, lr
- F ]:= 0
- convert_paletteentry_to_rgb
- link("udivide_255")
- [OPT pass%
- KR; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ; In R0 = &bbggrr??
- ; Out R0 = &000r.rrrr
- ; R1 = &000g.gggg
- ; R2 = &000b.bbbb
- R .convert_paletteentry_to_rgb
- S& STMFD (sp)!, {R4-R5, lr}
- MOV R4, R0
- U" MOV R5, #&00ff0000
- V=
- R0, R5, R4, LSR #8 ; &00bb0000
- W@ BL udivide_255 ; &000b.bbbb
- STMFD (sp)!, {R0}
- Y=
- R0, R5, R4 ; &00gg0000
- Z@ BL udivide_255 ; &000g.gggg
- STMFD (sp)!, {R0}
- \=
- R0, R5, R4, LSL #8 ; &00rr0000
- ]@ BL udivide_255 ; &000r.rrrr
- ^. LDMFD (sp)!, {R1-R2, R4-R5, pc}^
- _ ]:= 0
- xconvert_rgb_to_cmyk
- [OPT pass%
- cR; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ; In R0 = &000r.rrrr
- ; R1 = &000g.gggg
- ; R2 = &000b.bbbb
- ; Out R0 = &000c.cccc
- ; R1 = &000y.yyyy
- ; R2 = &000m.mmmm
- ; R3 = &000k.kkkk
- .xconvert_rgb_to_cmyk
- n3 SWI "XColourTrans_ConvertRGBToCMYK"
- MOV pc, lr
- p ]:= 0
- xconvert_rgb_to_hsv
- [OPT pass%
- tR; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ; In R0 = &000r.rrrr
- ; R1 = &000g.gggg
- ; R2 = &000b.bbbb
- y>; Out R0 = &0hhh.hhhh (or -1 if achromatic, ie r==g==b)
- ; R1 = &000s.ssss
- ; R2 = &000v.vvvv
- .xconvert_rgb_to_hsv
- CMP R0, R1
- @ CMPeq R1, R2 ; Achromatic
- K MVNeq R0, #
- (-1) ; So undefined (sentinel)
- MOVeq R1, #0
- 2 SWIne "XColourTrans_ConvertRGBToHSV"
- MOV pc, lr
- ]:= 0
- convert_rgb_to_paletteentry
- [OPT pass%
- R; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ; In R0 = &000r.rrrr
- ; R1 = &000g.gggg
- ; R2 = &000b.bbbb
- ; Out R0 = &bbggrr00
- .convert_rgb_to_paletteentry
- I RSB R2, R2, R2, LSL #8 ; R2= blue * &ff.0000
- # MOVS R2, R2, LSR #16
- C ADDcs R2, R2, #1 ; R2= &000000bb
- J RSB R1, R1, R1, LSL #8 ; R1= green * &ff.0000
- # MOVS R1, R1, LSR #16
- C ADC R1, R1, R2, LSL #8 ; R1= &0000bbgg
- H RSB R0, R0, R0, LSL #8 ; R0= red * &ff.0000
- # MOVS R0, R0, LSR #16
- C ADC R0, R0, R1, LSL #8 ; R0= &00bbggrr
- " MOV R0, R0, LSL #8
- MOVS pc, lr
- ]:= 0
- **********************************************************
- *** Macro DIVREM - rc := ra DIV rb; ra := ra REM rb ***
- *** rb preserved, rtemp corrupt ***
- *** Now up to 37% faster ***
- **********************************************************
- from Acorn AAsm header file 'macros'
- divrem(rc%, ra%, rb%, rtemp%)
- loop
- [OPT pass%
- MOV rtemp%, rb%
- ' CMP rtemp%, ra%, LSR #1
- *.loop MOVls rtemp%, rtemp%, LSL #1
- ' CMPls rtemp%, ra%, LSR #1
- Bls loop
- MOV rc%, #0
- .loop CMP ra%, rtemp%
- $ SUBcs ra%, ra%, rtemp%
- ! ADC rc%, rc%, rc%
- * MOV rtemp%, rtemp%, LSR #1
- CMP rtemp%, rb%
- Bcs loop
- ]:= 0
-