9 ;----- Standard header ------------------------------------------------------
14 ;----- External dependencies ------------------------------------------------
27 GET sapphire:_cs.kernel
30 ;----- Main code ------------------------------------------------------------
32 AREA |Sapphire$$Code|,CODE,READONLY
40 ; Use: Called by the colour picker
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
49 ; --- TEMPORARY CODE ---
51 LDMVSFD R13!,{R1-R3,PC} ;Return to caller
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
60 LDMFD R13!,{R1-R3,PC} ;Return to caller
63 hsv_dbName DCB "hsv",0
65 hsv__dbxDef CONTROL 0,hsvCircle,R10,0,0
73 CMP R0,#csEvent__close ;Is this a close event?
74 MOVNES PC,R14 ;No -- return then
75 STMFD R13!,{R0,R14} ;Save registers
82 ; --- hsv_plotCircle ---
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
93 ; Use: Plots an HSV colour circle at the position specified.
94 ; This should look really pretty as long as you're not using
100 STMFD R13!,{R0-R10,R12,R14} ;Save a job lot of regs
101 MOV R12,R5 ;Keep pointer to graphics blk
103 ; --- Set up the radius value ---
105 MOV R14,R4,LSR #9 ;Calculate the radius value
106 MUL R10,R14,R14 ;Now square it and keep it
108 ; --- Work out the pixel sizes ---
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
117 ; --- Start the main loop off ---
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
126 ; --- Get start x position into R1 ---
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
136 ; --- Get finish x position into R4 ---
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
144 ; --- And now get finish y position into R5 ---
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
155 00 MOV R8,R1 ;Start at beginning of row
157 ; --- Plot this rectangle ---
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
164 ; --- Calculate minx and maxx for given rectangle ---
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
172 ; --- Calculate various square values of x ---
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
181 ; --- Swap minx and maxx if we need to ---
183 MOV R14,#0 ;Clear our `swap' flag
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
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
195 ; --- Is the rectangle outside the circle ---
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
204 ; --- Plot a blank square ---
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
211 ; --- Is the rectangle on the circle edge? ---
213 20 CMP R8,#0 ;Is x < 0?
214 CMPLT R0,R7 ;Is x^2<maxx?
215 BLT %25hsv_plotCircle ;Yes -- plot the circle
217 CMPGE R1,R6 ;Is (x+xstep)>=minx
218 BLT %40hsv_plotCircle ;No -- plot an entire square
220 ; --- Plot an edge square then ---
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
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
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
242 CMP R1,R6 ;Is there anything to plot?
243 BGT %35hsv_plotCircle ;No -- skip this line out
246 MOV R0,#4 ;Move absolute
247 SWI OS_Plot ;Do the move
248 MOV R0,#5 ;Plot solid line absolute
251 SWI OS_Plot ;Do the move
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
259 ; --- Now plot an entire coloured square ---
261 40 BL hsv__setColour ;Set the colour
262 BL hsv__plotRectangle ;Plot it then
264 ; --- Find which square to do next ---
266 70 LDMFD R13!,{R1-R5,R8,R9} ;Get back registers
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
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
276 ; --- We did it then! ---
278 ADD R13,R13,#8 ;Skip past variable area
279 LDMFD R13!,{R0-R10,R12,PC}^ ;Jubilations and things
283 ; --- hsv__plotRectangle ---
285 ; On entry: R4 == width
287 ; R8 == x offset from centre
288 ; R9 == y offset from centre
289 ; R13+36 centre coordinates
291 ; On exit: R0-R2 corrupted
293 hsv__plotRectangle ROUT
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
304 SWI OS_Plot ;Plot the rectangle
305 MOVS PC,R14 ;And return to caller
309 ; --- hsv__setColour ---
311 ; On entry: R0 == x coord
320 STMFD R13!,{R0-R4,R14} ;Stack some registers
321 BL fxp_pol ;Calculate hue
322 MOV R3,R0 ;Preserve angle
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
353 LDMFD R13!,{R0-R4,PC}^ ;Return to caller
357 ; --- hsv__plot32k ---
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}
371 ; Use: Displays an HSV circle on the screen at a given location,
372 ; in a 16bpp mode, using direct screen access.
376 ; --- Limit the relative box positions ---
378 ADD R4,R3,#screen_dx ;Find the pixel positions
379 LDMIA R4,{R4,R5} ;Load them into registers
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
392 ; --- Find address of thing on the screen ---
394 MOV R5,R7 ;Remember left hand offset
395 MOV R6,R10 ;And right hand one
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
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
407 ; --- Convert things to pixels sizes ---
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
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
423 SUB R8,R5,#128 ;Work out x start position
424 SUB R7,R6,#128 ;And y start position
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
432 ; --- Plot the circle then ---
434 10hsv__plot32k MOV R0,#0 ;Clear buffer register
435 MOV R1,R12 ;Get the current address
437 BL hsv__getColour32 ;Get the colour then
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
447 ; --- Now the main plotting loop ---
449 20hsv__plot32k TST R1,#2 ;Is this an odd address?
450 STRNE R0,[R1,#-2] ;Yes -- done both half words
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
458 ; --- We've finished; do we have a half word left over? ---
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
468 ; --- Move onto the next row ---
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
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
486 ; --- hsv__getColour32 ---
488 ; On entry: R0 == colour word so far
489 ; R1 == current screen address
490 ; R3 == value (16.16)
494 ; On exit: R0 == updated colour word
497 ; Use: Determines the colour of the pixel at the given position
498 ; for a 32k colour mode
500 hsv__getColour32 ROUT
502 STMFD R13!,{R1-R5,R14} ;Stack some regsiters
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
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
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
523 MOV R1,R0 ;The saturation
525 MOV R0,R4 ;Get hue back
526 MOV R2,R3 ;Put value in R2
527 BL hsv_HSVToRGB ;Convert to RGB
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
536 ORR R14,R0,R1,LSL #5 ;Red and green
537 ORR R14,R14,R2,LSL #10 ;...blue
539 ORR R0,R14,R5,LSR #16 ;Return colour number
540 LDMFD R13!,{R1-R5,PC}^ ;Return to caller
542 ; --- Position is out of range ---
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
551 ; --- hsv__plot16m ---
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}
565 ; Use: Displays an HSV circle on the screen at a given location,
566 ; in a 32bpp mode, using direct screen access.
570 ; --- Limit the relative box positions ---
572 ADD R4,R3,#screen_dx ;Find the pixel positions
573 LDMIA R4,{R4,R5} ;Load them into registers
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
586 ; --- Find address of thing on the screen ---
588 MOV R5,R7 ;Remember left hand offset
589 MOV R6,R10 ;And right hand one
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
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
601 ; --- Convert things to pixels sizes ---
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
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
617 SUB R8,R5,#128 ;Work out x start position
618 SUB R7,R6,#128 ;And y start position
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
626 ; --- Plot the circle then ---
628 10hsv__plot16m MOV R1,R12 ;Get the current address
630 ; --- Now the main plotting loop ---
632 20hsv__plot16m BL hsv__getColour16 ;Get the colour then
633 STR R0,[R1],#4 ;Yes -- done both half words
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
639 ; --- Move onto the next row ---
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
648 LDMFD R13!,{R0-R12,PC}^ ;Return to caller
652 ; --- hsv__getColour16--
654 ; On entry: R3 == value (16.16)
658 ; On exit: R0 == updated colour word
660 ; Use: Determines the colour of the pixel at the given position
661 ; for a 32m colour mode
663 hsv__getColour16 ROUT
665 STMFD R13!,{R1-R4,R14} ;Stack some regsiters
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
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
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
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
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
698 ORR R0,R2,R0,LSR #16 ;Get red & blue components
699 ORR R0,R0,R1,LSR #8 ;And green
701 LDMFD R13!,{R1-R4,PC}^ ;Return to caller
705 ; --- hsv__plotCircle ---
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
713 ; Use: Dispatches to the most suitable hsv plotting routine for
718 STMFD R13!,{R0-R12,R14} ;Save lots of registers
720 ; --- Work out the minimum coordinates ---
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
728 ; --- Try to dispatch ---
730 MOV R4,R0 ;Look after left hand side
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?
741 LDMFD R13!,{R0-R12,PC}^ ;Return to caller
745 ; --- The dbx control ---
750 DCD dbxMask_redraw+dbxMask_click
752 CMP R0,#dbxEvent_click
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
763 10 STMFD R13!,{R0-R5,R14}
772 LDMFD R13!,{R0-R5,PC}^
779 ; On entry: R0 == number to find square root of
781 ; On exit: R0 == square root of number passed in
783 ; Use: Calculates the square root of the number passed to
784 ; the nearest integer
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
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
800 SUBS R5,R5,#1 ;Decrement iteration count
801 BEQ %01sqrt ;Too low -- skip to end
803 CMP R4,R3 ;Is solution same as last?
804 MOVNE R3,R4 ;No -- remember result
805 BNE %00sqrt ;...and keep trying
807 01sqrt MOV R0,R4 ;Return root in R0
808 LDMFD R13!,{R1-R5,PC}^ ;Return to caller
813 ; --- HSV -> RGB conversion ---
817 ; On entry: R0 == integer to divide
819 ; On exit: R0 == quotient after division by 60
820 ; R1 == remainder after division by 60
822 ; Use: Divides an integer very quickly by 60.
824 ; [Generated by Straylight divc]
854 ; --- hsv_HSVToRGB ---
856 ; On entry: R0 == hue
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.
870 STMFD R13!,{R3-R7,R14} ;Stack some registers
872 CMP R0,#(360<<16) ;Is hue 360?
873 MOVEQ R0,#0 ;Yes -- make it 0
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
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)))
897 ; --- Find out which section number we are in ---
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
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
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
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
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
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
939 60hsv_HSVToRGB ADR R0,convert__error ;Point to the error message
940 SWI OS_GenerateError ;And generate an error
943 DCB "Fatal error: hsv_HSVToRGB -- section >5 reached",0
947 ;----- Workspace layout -----------------------------------------------------
949 AREA |Sapphire$$LibData|,CODE,READONLY
956 ;-- That's all, folks -------------------------------------------------------