home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Datafile PD-CD 3
/
PDCD_3.iso
/
utilities
/
utilsd
/
dithering
/
TestDither
(
.txt
)
< prev
Wrap
RISC OS BBC BASIC V Source
|
1994-02-08
|
15KB
|
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, L