Initial revision
[ssr] / StraySrc / Libraries / Sapphire / colSelect / s / hsv
1 ;
2 ; hsv.s
3 ;
4 ; HSV functions (TMA)
5 ;
6 ; © 1994 Straylight
7 ;
8
9 ;----- Standard header ------------------------------------------------------
10
11 GET libs:header
12 GET libs:swis
13
14 ;----- External dependencies ------------------------------------------------
15
16 GET sapphire:dbox
17 GET sapphire:divide
18 GET sapphire:fixedPt
19 GET sapphire:screen
20 GET sapphire:sqrt
21
22 GET sapphire:dbx.dbx
23
24 GET sapphire:string
25 GET sapphire:note
26
27 GET sapphire:_cs.kernel
28 GET sapphire:_cs.vars
29
30 ;----- Main code ------------------------------------------------------------
31
32 AREA |Sapphire$$Code|,CODE,READONLY
33
34 ; --- hsv_open ---
35 ;
36 ; On entry: --
37 ;
38 ; On exit: --
39 ;
40 ; Use: Called by the colour picker
41
42 EXPORT hsv_open
43 hsv_open ROUT
44
45 STMFD R13!,{R1-R3,R14} ;Stack the link register
46 ADR R0,hsv_dbName ;Point to dialogue box name
47 BL dbox_create ;Create the dialogue box
48
49 ; --- TEMPORARY CODE ---
50
51 LDMVSFD R13!,{R1-R3,PC} ;Return to caller
52 ADR R1,hsv__dbh
53 MOV R2,R10
54 MOV R3,R12
55 BL dbox_eventHandler
56 LDMVSFD R13!,{R1-R3,PC} ;Return to caller
57 ADR R1,hsv__dbxDef ;Point to the control defn
58 BL dbx_declare ;Declare it to dbx nicely
59
60 LDMFD R13!,{R1-R3,PC} ;Return to caller
61
62
63 hsv_dbName DCB "hsv",0
64
65 hsv__dbxDef CONTROL 0,hsvCircle,R10,0,0
66 ECTRL
67 DBXEND
68
69 LTORG
70
71 hsv__dbh ROUT
72
73 CMP R0,#csEvent__close ;Is this a close event?
74 MOVNES PC,R14 ;No -- return then
75 STMFD R13!,{R0,R14} ;Save registers
76 MOV R0,R9
77 BL dbox_destroy
78 LDMFD R13!,{R0,PC}^
79
80 LTORG
81
82 ; --- hsv_plotCircle ---
83 ;
84 ; On entry: R0 == x coord of centre of circle to plot
85 ; R1 == y coord of centre of circle to plot
86 ; R2 == x step (in OS units, must be power of 2)
87 ; R3 == y step (in OS units, must be power of 2)
88 ; R4 == value coordinate (in 16.16 form)
89 ; R5 == pointer to graphics rectangle block
90 ;
91 ; On exit: --
92 ;
93 ; Use: Plots an HSV colour circle at the position specified.
94 ; This should look really pretty as long as you're not using
95 ; RISC OS 2 :-(.
96
97 EXPORT hsv_plotCircle
98 hsv_plotCircle ROUT
99
100 STMFD R13!,{R0-R10,R12,R14} ;Save a job lot of regs
101 MOV R12,R5 ;Keep pointer to graphics blk
102
103 ; --- Set up the radius value ---
104
105 MOV R14,R4,LSR #9 ;Calculate the radius value
106 MUL R10,R14,R14 ;Now square it and keep it
107
108 ; --- Work out the pixel sizes ---
109
110 BL screen_getInfo ;Find out about the screen
111 LDMIA R0,{R6,R7} ;Load the eign factors
112 MOV R14,#1 ;We're going to shift this
113 MOV R6,R14,LSL R6 ;Calculate the x pixel size
114 MOV R7,R14,LSL R7 ;And the y pixel size
115 STMFD R13!,{R6,R7} ;Save these for later use
116
117 ; --- Start the main loop off ---
118
119 LDR R9,[R12,#12] ;Get top of the rectangle
120 SUB R9,R9,R1 ;Subtract the circle centre
121 CMP R9,#127 ;Is the rectangle too high?
122 MOVGT R9,#127 ;Yes -- start at circle top
123 SUB R14,R3,#1 ;Turn ystep into bitmask
124 BIC R9,R9,R14 ;And align to multiple nicely
125
126 ; --- Get start x position into R1 ---
127
128 LDR R1,[R12,#0] ;Get left hand side of area
129 LDR R14,[R13,#8] ;Load the centre position
130 SUB R1,R1,R14 ;Subtract to get offset
131 CMP R1,#-128 ;Is it too far to the left?
132 MOVLT R1,#-128 ;Yes -- fix it up
133 SUB R14,R2,#1 ;Turn xstep into bitmask
134 BIC R1,R1,R14 ;Align to step value nicely
135
136 ; --- Get finish x position into R4 ---
137
138 LDR R4,[R12,#8] ;Get the right hand side pos
139 LDR R0,[R13,#8] ;Load the x centre position
140 SUB R4,R4,R0 ;Convert to offset
141 CMP R4,#128 ;Is this off the right side?
142 MOVGT R4,#128 ;Yes -- stop being silly then
143
144 ; --- And now get finish y position into R5 ---
145
146 LDR R5,[R12,#4] ;Get the bottom pos
147 LDR R0,[R13,#12] ;Load the y centre position
148 SUB R5,R5,R0 ;Convert to offset
149 SUB R5,R5,R3 ;Get the bottom of the sqr
150 CMP R5,#-128 ;Is this off the bottom?
151 MOVLT R5,#-128 ;Yes -- don't be silly then
152
153 ; --- Plot a row ---
154
155 00 MOV R8,R1 ;Start at beginning of row
156
157 ; --- Plot this rectangle ---
158
159 01 LDMIA R13,{R6,R7} ;Load pixel widths and things
160 STMFD R13!,{R1-R5,R8,R9} ;Save some useful things
161 SUB R4,R2,R6 ;xstep-dx
162 SUB R5,R3,R7 ;ystep-dy
163
164 ; --- Calculate minx and maxx for given rectangle ---
165
166 MUL R14,R9,R9 ;Get y^2
167 SUB R6,R10,R14 ;Calculate minx
168 ADD R0,R9,R5 ;y+ystep-dy
169 MUL R14,R0,R0 ;(y+ystep-dy)^2
170 SUB R7,R10,R14 ;Calculate maxx
171
172 ; --- Calculate various square values of x ---
173
174 MUL R0,R8,R8 ;Get x^2
175 ADD R14,R8,R2 ;Get x+xstep
176 MUL R1,R14,R14 ;And square that too
177 CMP R8,#0 ;Is x negative
178 RSBLT R0,R0,#0 ;Yes -- make R0 -ve
179 RSBLT R1,R1,#0 ;...and make R1 -ve
180
181 ; --- Swap minx and maxx if we need to ---
182
183 MOV R14,#0 ;Clear our `swap' flag
184 CMP R8,#0 ;Is x < 0
185 EORGE R14,R14,#1 ;No -- toggle swap flag
186 RSBLT R6,R6,#0 ;Yes -- make it -ve
187 RSBLT R7,R7,#0 ;...and that too
188 CMP R9,#0 ;Is y < 0
189 EORLT R14,R14,#1 ;Yes -- toggle swap flag
190 TST R14,#1 ;Do we need to swap?
191 EORNE R6,R6,R7 ;Yes -- swap them round
192 EORNE R7,R6,R7
193 EORNE R6,R6,R7
194
195 ; --- Is the rectangle outside the circle ---
196
197 CMP R1,R6 ;Is (x+xstep)^2<minx?
198 CMPLT R8,#0 ;Yes -- ensure x<0
199 BLT %10hsv_plotCircle ;It is -- plot a rectangle
200 CMP R0,R7 ;Is x^2>=maxx?
201 CMPGE R8,#0 ;Yes -- is x>=0
202 BLT %20hsv_plotCircle ;No -- Try an edge rectangle
203
204 ; --- Plot a blank square ---
205
206 10 MOV R0,#1 ;Wimp colour 1
207 SWI Wimp_SetColour ;Set the colour
208 BL hsv__plotRectangle ;Plot the rectangle
209 B %70hsv_plotCircle ;And branch to the end
210
211 ; --- Is the rectangle on the circle edge? ---
212
213 20 CMP R8,#0 ;Is x < 0?
214 CMPLT R0,R7 ;Is x^2<maxx?
215 BLT %25hsv_plotCircle ;Yes -- plot the circle
216 CMP R8,#0 ;Is x>=0
217 CMPGE R1,R6 ;Is (x+xstep)>=minx
218 BLT %40hsv_plotCircle ;No -- plot an entire square
219
220 ; --- Plot an edge square then ---
221
222 25 MOV R0,#1 ;Wimp colour 1
223 SWI Wimp_SetColour ;Set the colour
224 BL hsv__plotRectangle ;Plot the rectangle
225 BL hsv__setColour ;Set the correct colour
226 ADD R7,R9,R5 ;Our final loop value
227 ADD R14,R13,#36 ;Point to centre coords
228 LDMIA R14,{R3,R5} ;Get the centre coordinates
229
230 30 MUL R14,R9,R9 ;y^2
231 SUBS R0,R10,R14 ;Get r^2-y^2
232 BLT %35hsv_plotCircle ;Yes -- go round loop again
233 ; BL sqrt ;Calculate the square root
234
235 CMP R8,#0 ;Is x<0?
236 RSBLT R1,R0,#0 ;Yes -- get xstart pos
237 ADDLT R6,R8,R4 ;...and xend position
238 MOVGE R1,R8 ;No -- this xstart
239 LDRGE R6,[R13,#28] ;...get dx
240 SUBGE R6,R0,R6 ;...and calc xend pos
241
242 CMP R1,R6 ;Is there anything to plot?
243 BGT %35hsv_plotCircle ;No -- skip this line out
244 ADD R1,R1,R3 ;x0
245 ADD R2,R9,R5 ;y0
246 MOV R0,#4 ;Move absolute
247 SWI OS_Plot ;Do the move
248 MOV R0,#5 ;Plot solid line absolute
249 ADD R1,R3,R6 ;x1
250 ADD R2,R9,R5 ;y1
251 SWI OS_Plot ;Do the move
252
253 35 LDR R14,[R13,#32] ;Get dy
254 ADD R9,R9,R14 ;Increment y value
255 CMP R9,R7 ;Are we at the end?
256 BLE %30hsv_plotCircle ;And keep ploting lines
257 B %70 ;Finished this square
258
259 ; --- Now plot an entire coloured square ---
260
261 40 BL hsv__setColour ;Set the colour
262 BL hsv__plotRectangle ;Plot it then
263
264 ; --- Find which square to do next ---
265
266 70 LDMFD R13!,{R1-R5,R8,R9} ;Get back registers
267
268 ADD R8,R8,R2 ;Increment R8 nicely
269 CMP R8,R4 ;Have we finished a row?
270 BLT %01hsv_plotCircle ;No -- do some more then
271
272 SUB R9,R9,R3 ;Move down to the next row
273 CMP R9,R5 ;Have we finished it yet?
274 BGE %00hsv_plotCircle ;No -- do the next row
275
276 ; --- We did it then! ---
277
278 ADD R13,R13,#8 ;Skip past variable area
279 LDMFD R13!,{R0-R10,R12,PC}^ ;Jubilations and things
280
281 LTORG
282
283 ; --- hsv__plotRectangle ---
284 ;
285 ; On entry: R4 == width
286 ; R5 == height
287 ; R8 == x offset from centre
288 ; R9 == y offset from centre
289 ; R13+36 centre coordinates
290 ;
291 ; On exit: R0-R2 corrupted
292
293 hsv__plotRectangle ROUT
294
295 ADD R0,R13,#36 ;Point to circle centre
296 LDMIA R0,{R1,R2} ;Load the coordinates
297 MOV R0,#4 ;Move cursor absolute
298 ADD R1,R1,R8 ;To this x coord
299 ADD R2,R2,R9 ;And this y coord
300 SWI OS_Plot ;Do the move
301 MOV R0,#97 ;Rectangle fill relative
302 MOV R1,R4 ;This wide
303 MOV R2,R5 ;This high
304 SWI OS_Plot ;Plot the rectangle
305 MOVS PC,R14 ;And return to caller
306
307 LTORG
308
309 ; --- hsv__setColour ---
310 ;
311 ; On entry: R0 == x coord
312 ; R1 == y coord
313 ; R10 == radius^2
314 ; R13+52 == value
315 ;
316 ; On exit: --
317
318 hsv__setColour ROUT
319
320 STMFD R13!,{R0-R4,R14} ;Stack some registers
321 BL fxp_pol ;Calculate hue
322 MOV R3,R0 ;Preserve angle
323
324 MUL R14,R1,R1 ;Get y^2
325 MUL R0,R2,R2 ;Get x^2
326 ADD R0,R0,R14 ;Add them
327 MOV R1,R10 ;Get radius^2
328 MOV R0,R0,LSL#16 ;Prepare for division
329 CMP R1,#0 ;Will we divide by 0?
330 BLNE div_round ;No -- perform the division
331 MOVEQ R0,#0 ;Yes -- make it 0 for luck
332 MOV R1,R0 ;The saturation
333 MOV R0,R3 ;Get hue back
334 LDR R2,[R13,#76] ;Get value
335 BL hsv_HSVToRGB ;Convert to RGB
336 RSB R0,R0,R0,LSL#8 ;Multiple by 255
337 RSB R1,R1,R1,LSL#8 ;Multiple by 255
338 RSB R2,R2,R2,LSL#8 ;Multiple by 255
339 AND R0,R0,#&FF0000 ;Ensure it's 0-255
340 AND R1,R1,#&FF0000 ;Ensure it's 0-255
341 AND R2,R2,#&FF0000 ;Ensure it's 0-255
342 MOV R0,R0,LSR#8 ;Set up red component
343 ORR R0,R0,R1 ;And green component
344 ORR R0,R0,R2,LSL#8 ;And finally blue
345 MOV R14,R0 ;Preserve R0
346 MOV R3,#&100 ;The colourTrans flags
347 MOV R4,#0 ;GCOL action
348 SWI XColourTrans_SetGCOL ;Set the colour
349 MOVVS R3,#0 ;Try without dither
350 MOVVS R0,R14 ;Get colour back
351 SWIVS ColourTrans_SetGCOL ;Set the colour
352
353 LDMFD R13!,{R0-R4,PC}^ ;Return to caller
354
355 LTORG
356
357 ; --- hsv__plot32k ---
358 ;
359 ; On entry: R0 == left hand side of colour square to plot
360 ; R1 == bottom edge of colour square to plot
361 ; R2 == pointer to graphics window block
362 ; R3 == pointer to screen information block
363 ; R7 == unlimited minimum x position to plot
364 ; R8 == unlimited minimum y position to plot
365 ; R9 == unlimited maximum x position to plot
366 ; R10 == unlimited maximum y position to plot
367 ; On stack: saved {R0-R12,R14}
368 ;
369 ; On exit: --
370 ;
371 ; Use: Displays an HSV circle on the screen at a given location,
372 ; in a 16bpp mode, using direct screen access.
373
374 hsv__plot32k ROUT
375
376 ; --- Limit the relative box positions ---
377
378 ADD R4,R3,#screen_dx ;Find the pixel positions
379 LDMIA R4,{R4,R5} ;Load them into registers
380
381 CMP R7,#0 ;Is min x too small?
382 MOVLT R7,#0 ;Yes -- raise it to 0
383 CMP R8,#0 ;Is min y too small?
384 MOVLT R8,#0 ;Yes --- raise that too
385 CMP R9,#256 ;Is the max x too large?
386 MOVGT R9,#256 ;Yes -- reduce it then
387 CMP R10,#256 ;Is the max y too large?
388 MOVGT R10,#256 ;Yes -- reduce it then
389 SUB R9,R9,R4 ;Make this inclusive
390 SUB R10,R10,R5 ;Make this inclusive too
391
392 ; --- Find address of thing on the screen ---
393
394 MOV R5,R7 ;Remember left hand offset
395 MOV R6,R10 ;And right hand one
396
397 SUB R9,R9,R7 ;Work out width
398 SUB R8,R10,R8 ;And height
399 ADD R7,R7,R0 ;Work out left hand side
400 ADD R10,R10,R1 ;And maximum y
401
402 SUB R13,R13,#20 ;Space for our vdu vars
403 ADR R0,hsv__vduVars ;Point to the var numbers
404 MOV R1,R13 ;Point to our output block
405 SWI OS_ReadVduVariables ;Get the values nicely
406
407 ; --- Convert things to pixels sizes ---
408
409 LDMIA R13!,{R3,R4} ;Load out eig factors
410 MOV R7,R7,LSR R3 ;Convert left hand side
411 MOV R8,R8,LSR R4 ;And height
412 MOV R9,R9,LSR R3 ;The width too
413 MOV R10,R10,LSR R4 ;And the top coord
414
415 LDMIA R13!,{R0,R1,R2} ;Load other vdu vars
416 SUB R14,R1,R10 ;Shift origin to top left
417 MLA R0,R14,R2,R0 ;Work out address of row
418 ADD R12,R0,R7,LSL #1 ;Work out left address
419 ADD R11,R12,R9,LSL #1 ;Work out right hand side too
420 MOV R9,R2 ;Put scan line width in R9
421 MOV R10,R8 ;And height in R10
422
423 SUB R8,R5,#128 ;Work out x start position
424 SUB R7,R6,#128 ;And y start position
425
426 MOV R14,#1 ;Get a useful value
427 MOV R6,R14,LSL R3 ;x step
428 MOV R5,R14,LSL R4 ;y step
429 MOV R4,R8 ;Initial x value
430 MOV R3,#&10000 ;Value
431
432 ; --- Plot the circle then ---
433
434 10hsv__plot32k MOV R0,#0 ;Clear buffer register
435 MOV R1,R12 ;Get the current address
436
437 BL hsv__getColour32 ;Get the colour then
438
439 TST R1,#2 ;Is this address aligned?
440 BEQ %20hsv__plot32k ;Yes -- start at main loop
441 LDR R14,[R1,#-2] ;No -- load word from here
442 MOV R14,R14,LSL #16 ;Shift all the way up
443 ORR R14,R0,R14,LSR #16 ;Build the replacement word
444 STR R14,[R1,#-2] ;And store in frame buffer
445 B %25hsv__plot32k ;Jump to end of loop
446
447 ; --- Now the main plotting loop ---
448
449 20hsv__plot32k TST R1,#2 ;Is this an odd address?
450 STRNE R0,[R1,#-2] ;Yes -- done both half words
451
452 25hsv__plot32k ADD R1,R1,#2 ;Move onto next pixel
453 ADD R8,R8,R6 ;Increment x position
454 CMP R1,R11 ;Are we at the line end?
455 BLLS hsv__getColour32 ;No -- get the colour then
456 BLS %20hsv__plot32k ;...and go round for more
457
458 ; --- We've finished; do we have a half word left over? ---
459
460 30hsv__plot32k TST R1,#2 ;Is the address odd?
461 BEQ %35hsv__plot32k ;No -- jump ahead
462 LDR R14,[R1,#-2] ;Yes -- read old word
463 MOV R0,R0,LSR #16 ;Put buffer value in low hw
464 MOV R14,R14,LSR #16 ;Shift down screen value too
465 ORR R14,R0,R14,LSL #16 ;Build up correct word
466 STR R14,[R1,#-2] ;Store this word away
467
468 ; --- Move onto the next row ---
469
470 35hsv__plot32k ADD R12,R12,R9 ;Move left address down
471 ADD R11,R11,R9 ;And the right address
472 SUB R7,R7,R5 ;Decrement the y position
473 MOV R8,R4 ;Initial start x position
474 SUBS R10,R10,#1 ;Decrement the line count
475 BCS %10hsv__plot32k ;And keep on going
476 LDMFD R13!,{R0-R12,PC}^ ;Return to caller
477
478 LTORG
479
480 hsv__vduVars DCD 4,5 ;X and Y eigen factors
481 DCD 149 ;Start of display memory
482 DCD 12 ;How high is the screen
483 DCD 6 ;Width of scan line in pixels
484 DCD -1
485
486 ; --- hsv__getColour32 ---
487 ;
488 ; On entry: R0 == colour word so far
489 ; R1 == current screen address
490 ; R3 == value (16.16)
491 ; R7 == y position
492 ; R8 == x position
493 ;
494 ; On exit: R0 == updated colour word
495 ;
496 ;
497 ; Use: Determines the colour of the pixel at the given position
498 ; for a 32k colour mode
499
500 hsv__getColour32 ROUT
501
502 STMFD R13!,{R1-R5,R14} ;Stack some regsiters
503
504 MOV R5,R0 ;Look after old colour
505 MUL R2,R7,R7 ;Get y^2
506 MUL R14,R8,R8 ;Get x^2
507 ADD R2,R2,R14 ;Get x^2+y^2
508 CMP R2,#&4000 ;Is this in range?
509 BCS %50hsv__getColour32 ;No -- do really clever stuff
510
511 MOV R0,R8 ;Put x position in R0
512 MOV R1,R7 ;And x position in R1
513 BL fxp_pol ;Calculate hue
514 MOV R4,R0 ;Preserve angle
515
516 MOV R0,R2 ;x^2 + y^2
517 MOV R1,#&4000 ;Get radius^2
518 MOV R0,R0,LSL#16 ;Prepare for division
519 CMP R1,#0 ;Will we divide by 0?
520 BLNE div_round ;No -- perform the division
521 MOVEQ R0,#0 ;Yes -- make it 0 for luck
522
523 MOV R1,R0 ;The saturation
524
525 MOV R0,R4 ;Get hue back
526 MOV R2,R3 ;Put value in R2
527 BL hsv_HSVToRGB ;Convert to RGB
528
529 RSB R0,R0,R0,LSL#5 ;Multiple by 31
530 RSB R1,R1,R1,LSL#5 ;Multiple by 31
531 RSB R2,R2,R2,LSL#5 ;Multiple by 31
532 AND R0,R0,#&1F0000 ;Ensure it's 0-31
533 AND R1,R1,#&1F0000 ;Ensure it's 0-31
534 AND R2,R2,#&1F0000 ;Ensure it's 0-31
535
536 ORR R14,R0,R1,LSL #5 ;Red and green
537 ORR R14,R14,R2,LSL #10 ;...blue
538
539 ORR R0,R14,R5,LSR #16 ;Return colour number
540 LDMFD R13!,{R1-R5,PC}^ ;Return to caller
541
542 ; --- Position is out of range ---
543
544 50 LDR R14,[R1,#0] ;Load halfword at address
545 MOV R14,R14,LSL #16 ;Put it into top halfword
546 ORR R0,R14,R5,LSR #16 ;Build up new colour value
547 LDMFD R13!,{R1-R5,PC}^ ;And return to caller
548
549 LTORG
550
551 ; --- hsv__plot16m ---
552 ;
553 ; On entry: R0 == left hand side of colour square to plot
554 ; R1 == bottom edge of colour square to plot
555 ; R2 == pointer to graphics window block
556 ; R3 == pointer to screen information block
557 ; R7 == unlimited minimum x position to plot
558 ; R8 == unlimited minimum y position to plot
559 ; R9 == unlimited maximum x position to plot
560 ; R10 == unlimited maximum y position to plot
561 ; On stack: saved {R0-R12,R14}
562 ;
563 ; On exit: --
564 ;
565 ; Use: Displays an HSV circle on the screen at a given location,
566 ; in a 32bpp mode, using direct screen access.
567
568 hsv__plot16m ROUT
569
570 ; --- Limit the relative box positions ---
571
572 ADD R4,R3,#screen_dx ;Find the pixel positions
573 LDMIA R4,{R4,R5} ;Load them into registers
574
575 CMP R7,#0 ;Is min x too small?
576 MOVLT R7,#0 ;Yes -- raise it to 0
577 CMP R8,#0 ;Is min y too small?
578 MOVLT R8,#0 ;Yes --- raise that too
579 CMP R9,#256 ;Is the max x too large?
580 MOVGT R9,#256 ;Yes -- reduce it then
581 CMP R10,#256 ;Is the max y too large?
582 MOVGT R10,#256 ;Yes -- reduce it then
583 SUB R9,R9,R4 ;Make this inclusive
584 SUB R10,R10,R5 ;Make this inclusive too
585
586 ; --- Find address of thing on the screen ---
587
588 MOV R5,R7 ;Remember left hand offset
589 MOV R6,R10 ;And right hand one
590
591 SUB R9,R9,R7 ;Work out width
592 SUB R8,R10,R8 ;And height
593 ADD R7,R7,R0 ;Work out left hand side
594 ADD R10,R10,R1 ;And maximum y
595
596 SUB R13,R13,#20 ;Space for our vdu vars
597 ADR R0,hsv__vduVars ;Point to the var numbers
598 MOV R1,R13 ;Point to our output block
599 SWI OS_ReadVduVariables ;Get the values nicely
600
601 ; --- Convert things to pixels sizes ---
602
603 LDMIA R13!,{R3,R4} ;Load out eig factors
604 MOV R7,R7,LSR R3 ;Convert left hand side
605 MOV R8,R8,LSR R4 ;And height
606 MOV R9,R9,LSR R3 ;The width too
607 MOV R10,R10,LSR R4 ;And the top coord
608
609 LDMIA R13!,{R0,R1,R2} ;Load other vdu vars
610 SUB R14,R1,R10 ;Shift origin to top left
611 MLA R0,R14,R2,R0 ;Work out address of row
612 ADD R12,R0,R7,LSL #2 ;Work out left address
613 ADD R11,R12,R9,LSL #2 ;Work out right hand side too
614 MOV R9,R2 ;Put scan line width in R9
615 MOV R10,R8 ;And height in R10
616
617 SUB R8,R5,#128 ;Work out x start position
618 SUB R7,R6,#128 ;And y start position
619
620 MOV R14,#1 ;Get a useful value
621 MOV R6,R14,LSL R3 ;x step
622 MOV R5,R14,LSL R4 ;y step
623 MOV R4,R8 ;Initial x value
624 MOV R3,#&10000 ;Value
625
626 ; --- Plot the circle then ---
627
628 10hsv__plot16m MOV R1,R12 ;Get the current address
629
630 ; --- Now the main plotting loop ---
631
632 20hsv__plot16m BL hsv__getColour16 ;Get the colour then
633 STR R0,[R1],#4 ;Yes -- done both half words
634
635 25hsv__plot16m ADD R8,R8,R6 ;Increment x position
636 CMP R1,R11 ;Are we at the line end?
637 BLS %20hsv__plot16m ;...and go round for more
638
639 ; --- Move onto the next row ---
640
641 30hsv__plot16m ADD R12,R12,R9 ;Move left address down
642 ADD R11,R11,R9 ;And the right address
643 SUB R7,R7,R5 ;Decrement the y position
644 MOV R8,R4 ;Initial start x position
645 SUBS R10,R10,#1 ;Decrement the line count
646 BCS %10hsv__plot16m ;And keep on going
647
648 LDMFD R13!,{R0-R12,PC}^ ;Return to caller
649
650 LTORG
651
652 ; --- hsv__getColour16--
653 ;
654 ; On entry: R3 == value (16.16)
655 ; R7 == y position
656 ; R8 == x position
657 ;
658 ; On exit: R0 == updated colour word
659 ;
660 ; Use: Determines the colour of the pixel at the given position
661 ; for a 32m colour mode
662
663 hsv__getColour16 ROUT
664
665 STMFD R13!,{R1-R4,R14} ;Stack some regsiters
666
667 MUL R2,R7,R7 ;Get y^2
668 MUL R4,R8,R8 ;Get x^2
669 ADD R2,R2,R4 ;Get x^2+y^2
670 CMP R2,#&4000 ;Is this in range?
671 LDRCS R0,[R1,#0] ;No -- load previous colour
672 LDMCSFD R13!,{R1-R4,PC}^ ;And return to caller
673
674 MOV R0,R8 ;Put x position in R0
675 MOV R1,R7 ;And x position in R1
676 BL fxp_pol ;Calculate hue
677 MOV R4,R0 ;Preserve angle
678
679 MOV R0,R2 ;x^2 + y^2
680 MOV R1,#&4000 ;Get radius^2
681 MOV R0,R0,LSL#16 ;Prepare for division
682 CMP R1,#0 ;Will we divide by 0?
683 BLNE div_round ;No -- perform the division
684 MOVEQ R0,#0 ;Yes -- make it 0 for luck
685
686 MOV R1,R0 ;The saturation
687 MOV R0,R4 ;Get hue back
688 MOV R2,R3 ;Put value in R2
689 BL hsv_HSVToRGB ;Convert to RGB
690
691 RSB R0,R0,R0,LSL#8 ;Multiple by 255
692 RSB R1,R1,R1,LSL#8 ;Multiple by 255
693 RSB R2,R2,R2,LSL#8 ;Multiple by 255
694 AND R0,R0,#&FF0000 ;Ensure it's 0-255
695 AND R1,R1,#&FF0000 ;Ensure it's 0-255
696 AND R2,R2,#&FF0000 ;Ensure it's 0-255
697
698 ORR R0,R2,R0,LSR #16 ;Get red & blue components
699 ORR R0,R0,R1,LSR #8 ;And green
700
701 LDMFD R13!,{R1-R4,PC}^ ;Return to caller
702
703 LTORG
704
705 ; --- hsv__plotCircle ---
706 ;
707 ; On entry: R0 == left hand side of colour square to plot
708 ; R1 == bottom edge of colour square to plot
709 ; R2 == pointer to graphics window block
710 ;
711 ; On exit: --
712 ;
713 ; Use: Dispatches to the most suitable hsv plotting routine for
714 ; the given mode.
715
716 hsv__plotCircle ROUT
717
718 STMFD R13!,{R0-R12,R14} ;Save lots of registers
719
720 ; --- Work out the minimum coordinates ---
721
722 LDMIA R2,{R7,R8,R9,R10} ;Load the coordinates out
723 SUB R7,R7,R0 ;Translate min x to relative
724 SUB R8,R8,R1 ;Translate min y too
725 SUB R9,R9,R0 ;Translate max x too
726 SUB R10,R10,R1 ;Translate max y
727
728 ; --- Try to dispatch ---
729
730 MOV R4,R0 ;Look after left hand side
731
732 BL screen_getInfo ;Get screen info block
733 MOV R3,R0 ;Put it in R3
734 MOV R0,R4 ;And get left hand side back
735 LDR R14,[R3,#screen_bpp] ;Load current bits/pixel
736 CMP R14,#16 ;Is this a 32K mode?
737 BEQ hsv__plot32k ;Yes -- well, go to it
738 CMP R14,#32 ;Is this a 32K mode?
739 BEQ hsv__plot16m
740
741 LDMFD R13!,{R0-R12,PC}^ ;Return to caller
742
743 LTORG
744
745 ; --- The dbx control ---
746
747 hsvCircle ROUT
748
749 DCD 0,0
750 DCD dbxMask_redraw+dbxMask_click
751
752 CMP R0,#dbxEvent_click
753 BEQ %10
754
755 STMFD R13!,{R0-R2,R10,R14} ;Stack some registers
756 MOV R10,R8 ;Put dbox data in R10
757 MOV R0,R2 ;Put bottom left in R0
758 MOV R1,R3 ;And bottom right in R1
759 MOV R2,R6 ;Put graphics rectangle in R2
760 BL hsv__plotCircle ;Plot the circle then
761 LDMFD R13!,{R0-R2,R10,PC}^ ;Return to caller
762
763 10 STMFD R13!,{R0-R5,R14}
764 MOV R0,R10
765 BL dbx_controlBBox
766 SUB R4,R4,R2
767 SUB R5,R5,R3
768 ADD R0,R2,R4,LSR #1
769 ADD R1,R3,R5,LSR #1
770 MOV R2,#128
771 SWI Constrain_Disc
772 LDMFD R13!,{R0-R5,PC}^
773
774 LTORG
775
776 [ 0=1
777 ; --- sqrt ---
778 ;
779 ; On entry: R0 == number to find square root of
780 ;
781 ; On exit: R0 == square root of number passed in
782 ;
783 ; Use: Calculates the square root of the number passed to
784 ; the nearest integer
785
786 sqrt ROUT
787
788 STMFD R13!,{R1-R5,R14} ;Stack some registers
789 MOV R4,R0,LSR#2 ;Get an approximation
790 MOV R3,#-1 ;The old value
791 MOV R2,R0 ;Keep this value
792 MOV R5,#10 ;Maximum number of iterations
793
794 00sqrt MOV R0,R2,ASR #1 ;Divide number to squareroot
795 MOVS R1,R4 ;By 2*our approximation
796 BEQ %01sqrt ;Divide by 0 -- leave now
797 BL div_round ;Round result to nearest
798 ADD R4,R0,R4,ASR #1 ;Add this to x/2
799
800 SUBS R5,R5,#1 ;Decrement iteration count
801 BEQ %01sqrt ;Too low -- skip to end
802
803 CMP R4,R3 ;Is solution same as last?
804 MOVNE R3,R4 ;No -- remember result
805 BNE %00sqrt ;...and keep trying
806
807 01sqrt MOV R0,R4 ;Return root in R0
808 LDMFD R13!,{R1-R5,PC}^ ;Return to caller
809
810 LTORG
811 ]
812
813 ; --- HSV -> RGB conversion ---
814
815 ; --- div60 ---
816 ;
817 ; On entry: R0 == integer to divide
818 ;
819 ; On exit: R0 == quotient after division by 60
820 ; R1 == remainder after division by 60
821 ;
822 ; Use: Divides an integer very quickly by 60.
823 ;
824 ; [Generated by Straylight divc]
825
826 div60 ROUT
827
828 STMFD R13!,{R2,R14}
829 MOVS R2,R0
830 RSBMI R0,R0,#0
831 MOV R1,R0
832
833 ADD R0,R0,R0,LSR#4
834 ADD R0,R0,R0,LSR#8
835 ADD R0,R0,R0,LSR#16
836
837 MOV R0,R0,LSR #6
838
839 RSB R14,R0,R0,LSL#4
840 MOV R14,R14,LSL#2
841
842 SUB R1,R1,R14
843 SUBS R1,R1,#60
844 ADDGE R0,R0,#1
845 ADDLT R1,R1,#60
846
847 CMP R2,#0
848 RSBMI R0,R0,#0
849 RSBMI R1,R1,#0
850 LDMFD R13!,{R2,PC}^
851
852 LTORG
853
854 ; --- hsv_HSVToRGB ---
855 ;
856 ; On entry: R0 == hue
857 ; R1 == saturation
858 ; R2 == value
859 ;
860 ; On exit: R0 == red
861 ; R1 == green
862 ; R2 == blue
863 ;
864 ; Use: Convert a colour in HSV to the equivalent in RGB notation.
865 ; All number are taken in 16.16 fixed point form. RGB values
866 ; range from 0 to 1 on output.
867
868 hsv_HSVToRGB ROUT
869
870 STMFD R13!,{R3-R7,R14} ;Stack some registers
871
872 CMP R0,#(360<<16) ;Is hue 360?
873 MOVEQ R0,#0 ;Yes -- make it 0
874
875 MOV R3,R1 ;Put saturation in R3
876 BL div60 ;Divide hue by 60
877 BIC R1,R0,#&FF0000 ;Get fractional part in R1
878 MOV R0,R0,LSR#16 ;And integer part in R0
879
880 MOV R4,R2,LSR#8 ;For multiplication
881 RSB R5,R3,#1<<16 ;1-saturation (16.16 form)
882 MOV R5,R5,LSR#8 ;Shift for division
883 MUL R5,R4,R5 ;Minimum=value*(1-saturation)
884 MOV R14,R3,LSR#8 ;Saturation >> 8
885 MOV R6,R1,LSR#8 ;Fractional >> 8
886 MUL R6,R14,R6 ;Saturation*fractional
887 RSB R6,R6,#1<<16 ;1-(previous result)
888 MOV R6,R6,LSR#8 ;Prepare for multiplication
889 MUL R6,R4,R6 ;Inverse1=value*(prev result)
890 RSB R7,R1,#1<<16 ;1-fractional
891 MOV R7,R7,LSR#8 ;Prepare for multiplication
892 MUL R7,R14,R7 ;Saturation*(1-fractional)
893 RSB R7,R7,#1<<16 ;1-(sat*(1-fractional))
894 MOV R7,R7,LSR#8 ;Prepare for multiplication
895 MUL R7,R4,R7 ;Value*(1-(sat*(1-frac)))
896
897 ; --- Find out which section number we are in ---
898
899 CMP R0,#0 ;Section 0?
900 BNE %10hsv_HSVToRGB ;No -- try next one
901 MOV R0,R2 ;Red = value
902 MOV R1,R7 ;Green = inverse2
903 MOV R2,R5 ;Blue = minimum
904 LDMFD R13!,{R3-R7,PC}^ ;Return to caller
905
906 10hsv_HSVToRGB CMP R0,#1 ;Section 1?
907 BNE %20hsv_HSVToRGB ;No -- try next one
908 MOV R0,R6 ;Red = inverse1
909 MOV R1,R2 ;Green = value
910 MOV R2,R5 ;Blue = minimum
911 LDMFD R13!,{R3-R7,PC}^ ;Return to caller
912
913 20hsv_HSVToRGB CMP R0,#2 ;Section 2?
914 BNE %30hsv_HSVToRGB ;No -- try next one
915 MOV R0,R5 ;Red = minimum
916 MOV R1,R2 ;Green = value
917 MOV R2,R7 ;Blue = inverse2
918 LDMFD R13!,{R3-R7,PC}^ ;Return to caller
919
920 30hsv_HSVToRGB CMP R0,#3 ;Section 3?
921 BNE %40hsv_HSVToRGB ;No -- try next one
922 MOV R0,R5 ;Red = minimum
923 MOV R1,R6 ;Green = inverse1
924 LDMFD R13!,{R3-R7,PC}^ ;Return to caller
925
926 40hsv_HSVToRGB CMP R0,#4 ;Section 0?
927 BNE %50hsv_HSVToRGB ;No -- try next one
928 MOV R0,R7 ;Red = inverse2
929 MOV R1,R5 ;Green = minimum
930 LDMFD R13!,{R3-R7,PC}^ ;Return to caller
931
932 50hsv_HSVToRGB CMP R0,#5 ;Section 0?
933 BNE %60hsv_HSVToRGB ;No -- try next one
934 MOV R0,R2 ;Red = value
935 MOV R1,R5 ;Green = minimum
936 MOV R2,R6 ;Blue = inverse1
937 LDMFD R13!,{R3-R7,PC}^ ;Return to caller
938
939 60hsv_HSVToRGB ADR R0,convert__error ;Point to the error message
940 SWI OS_GenerateError ;And generate an error
941
942 convert__error DCD 1
943 DCB "Fatal error: hsv_HSVToRGB -- section >5 reached",0
944
945 LTORG
946
947 ;----- Workspace layout -----------------------------------------------------
948
949 AREA |Sapphire$$LibData|,CODE,READONLY
950
951 DCD 0
952 DCD 0
953 DCD 0
954 DCD 0
955
956 ;-- That's all, folks -------------------------------------------------------
957
958 END