chiark / gitweb /
Initial revision
[ssr] / StraySrc / SapphToys / !ColDemo / 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