Initial revision
[ssr] / StraySrc / SapphToys / !ColDemo / s / rgb
1 ;
2 ; rgb.s
3 ;
4 ; Handling the RGB colour model dialogue box
5 ;
6 ; © 1994 Straylight
7 ;
8
9 ;----- Standard header ------------------------------------------------------
10
11 GET libs:header
12 GET libs:swis
13
14 GET libs:stream
15
16 ;----- External dependencies ------------------------------------------------
17
18 GET sapphire:dbox
19 GET sapphire:divide
20 GET sapphire:idle
21 GET sapphire:roVersion
22 GET sapphire:screen
23 GET sapphire:win
24
25 GET sapphire:dbx.dbx
26 GET sapphire:dbx.arrow
27 GET sapphire:dbx.numWrite
28 GET sapphire:dbx.slider
29
30 GET sapphire:_cs.kernel
31 GET sapphire:_cs.vars
32
33 ;----- Main code ------------------------------------------------------------
34
35 AREA |Sapphire$$Code|,CODE,READONLY
36
37 ; --- rgb_open ---
38 ;
39 ; On entry: --
40 ;
41 ; On exit: --
42 ;
43 ; Use: Called by the colour picker
44
45 EXPORT rgb_open
46 rgb_open ROUT
47
48 STMFD R13!,{R1-R3,R14} ;Stack the link register
49 ADR R0,rgb__dbName ;Point to dialogue box name
50 BL dbox_create ;Create the dialogue box
51 LDMVSFD R13!,{R1-R3,PC} ;Return now if it failed
52 STR R0,[R13,#-4]! ;Return dialogue handle in R0
53
54 ; --- Attach event handlers and things ---
55
56 ADR R1,rgb__dbHandler ;Point to my handler code
57 MOV R2,R10 ;Pass colour workspace in R10
58 MOV R3,R12 ;Pass my workspace in R12
59 BL dbox_eventHandler ;Register my event handler
60 ADR R1,rgb__dbxDef ;Point to the control defn
61 BL dbx_declare ;Declare it to dbx nicely
62
63 ; --- Set up the workspace ---
64
65 MOV R0,#0 ;Set the Red mapping
66 BL rgb__setMapping ;Set this as the mapping
67
68 ; --- Set up the dialogue box ---
69
70 LDR R0,[R13,#0] ;Load the dialogue handle
71 LDR R1,rgb__mapping ;Get the current mapping
72 ADD R1,R1,R1,LSL #2 ;Multiply by icon offset (5)
73 ADD R1,R1,#rgbIcon__radioR ;Add on to get icon number
74 MOV R2,#1 ;Please select this icon
75 BL dbox_select ;Select the right one
76
77 MOV R1,#rgbIcon__writeR ;Get the red writable icon
78 LDR R2,rgb__red ;Find the red value
79 LDR R2,[R2,#0] ;Load the red value
80 BL numWrite_set ;Set it in the icon
81
82 MOV R1,#rgbIcon__writeG ;Get the green writable icon
83 LDR R2,rgb__green ;Find the green value
84 LDR R2,[R2,#0] ;Load the green value
85 BL numWrite_set ;Set it in the icon
86
87 MOV R1,#rgbIcon__writeB ;Get the blue writable icon
88 LDR R2,rgb__blue ;Find the blue value
89 LDR R2,[R2,#0] ;Load the blue value
90 BL numWrite_set ;Set it in the icon
91 LDMFD R13!,{R0-R3,R14} ;Return to caller
92
93 rgb__dbName DCB "rgb",0
94
95 rgb__dbxDef CONTROL rgbIcon__square,rgbSquare,R10,0,0
96 ECTRL
97
98 SLIDER rgbIcon__slide1,R10,:INDEX: rgb__sl1Val, slFlag_horizontal + slFlag_colData,0,0,1,100
99 NUMWRT rgbIcon__writeR,0,100
100 ARROW rgbIcon__upR,1
101 ARROW rgbIcon__downR,-1
102
103 SLIDER rgbIcon__slide2,R10,:INDEX: rgb__sl2Val, slFlag_vertical + slFlag_colData,0,0,1,100
104 NUMWRT rgbIcon__writeG,0,100
105 ARROW rgbIcon__upG,1
106 ARROW rgbIcon__downG,-1
107
108 SLIDER rgbIcon__slide3,R10,:INDEX: rgb__sl3Val, slFlag_vertical + slFlag_colData,0,0,1,100
109 NUMWRT rgbIcon__writeB,0,100
110 ARROW rgbIcon__upB,1
111 ARROW rgbIcon__downB,-1
112
113 DBXEND
114
115 ; --- rgb__dbHandler ---
116 ;
117 ; On entry: R0 == dialogue box event code
118 ; R1-R7 == depend on the event
119 ; R9 == dialogue box handle of RGB panel
120 ; R10 == pointer to colour selector workspace
121 ; R12 == nothing much
122 ;
123 ; On exit: --
124 ;
125 ; Use: Handles events for the RGB panel.
126
127 rgb__dbHandler ROUT
128
129 ; --- Dispatch events to their destinations ---
130
131 CMP R0,#rgbIcon__radioR ;Is it the red view button?
132 CMPNE R0,#rgbIcon__radioG ;Or the green view button?
133 CMPNE R0,#rgbIcon__radioB ;Or the blue view button?
134 BEQ rgb__setView ;Yes -- set the new view
135
136 CMP R0,#csEvent__close ;Is it a close panel event?
137 BEQ rgb__closePanel ;Yes -- destroy the dialogue
138
139 CMP R0,#csEvent__newRes ;Is it a resolution change?
140 BEQ rgb__newRes ;Yes -- update the piccy then
141
142 CMP R0,#slider_event ;Is it a slider event?
143 BEQ rgb__slChange ;Yes -- do something then
144
145 CMP R0,#numWrite_event ;Is it a writable event?
146 BEQ rgb__wrChange ;Yes -- do something then
147
148 CMP R0,#arrow_event ;Is it an arrow event?
149 BEQ rgb__arChange ;Yes -- do something then
150
151 STMFD R13!,{R14} ;Save a register
152 SUB R14,R0,#rgbIcon__wCols ;Is it a WIMP colour box?
153 CMP R14,#16 ;Check it's in range
154 BLO rgb__wimpCol ;Yes -- handle it then
155
156 LDMFD R13!,{PC}^ ;Unknown -- return to caller
157
158 ; --- Change the panel view ---
159
160 rgb__setView ROUT
161
162 STMFD R13!,{R0-R3,R14} ;Save some registers
163 CMP R0,#rgbIcon__radioG ;Is it the green button?
164 MOVLT R3,#0 ;Lower -- it must be red
165 MOVEQ R3,#1 ;Equal -- must be green
166 MOVGT R3,#2 ;Greater -- must be blue
167 LDR R1,rgb__mapping ;Get the current mapping
168 CMP R3,R1 ;Is it the same?
169 LDMEQFD R13!,{R0-R3,PC}^ ;Yes -- return now then
170
171 ; --- Select the correct icon ---
172
173 MOV R0,R9 ;Load the dialogue handle
174 ADD R1,R1,R1,LSL #2 ;Multiply by icon offset (5)
175 ADD R1,R1,#rgbIcon__radioR ;Add on to get icon number
176 MOV R2,#0 ;Please deselect this icon
177 BL dbox_select ;Select the right one
178
179 ADD R1,R3,R3,LSL #2 ;Multiply by icon offset (5)
180 ADD R1,R1,#rgbIcon__radioR ;Add on to get icon number
181 MOV R2,#1 ;Please select this icon
182 BL dbox_select ;Select the right one
183
184 ; --- Update the dialogue box sliders etc. ---
185
186 MOV R0,R9 ;Get the dialogue box handle
187 MOV R1,#rgbIcon__square ;Get the colour square
188 BL dbx_qUpdate ;Get rid of the crosshair
189 MOV R0,R3 ;Pass mapping number
190 BL rgb__setMapping ;Redo all the mappings
191 BL rgb__updateSliders ;And redraw the sliders
192 MOV R0,R9 ;Get the dialogue box handle
193 MOV R1,#rgbIcon__square ;Get the colour square
194 BL dbx_update ;Redraw it nicely
195 LDMFD R13!,{R0-R3,PC}^ ;Return to caller
196
197 ; --- Update the RGB colour cube view ---
198
199 rgb__newRes ROUT
200
201 STMFD R13!,{R0,R1,R14} ;Save some registers
202 MOV R0,R9 ;Get the dialogue handle
203 MOV R1,#rgbIcon__square ;Get the colour square
204 BL dbx_qUpdate ;Get rid of the crosshair
205 BL dbx_update ;Redraw it nicely
206 LDMFD R13!,{R0,R1,PC}^ ;And return to caller
207
208 ; --- Update colour values ---
209
210 rgb__slChange ROUT
211
212 STMFD R13!,{R0-R2,R4,R14} ;Save some registers
213
214 ; --- Update the main dialogue's colour pot ---
215
216 BL rgb__colUpdate ;Update the colour pot
217
218 ; --- Now update the writable icon ---
219
220 LDR R2,[R13,#8] ;Load the slider icon
221 SUB R4,R2,#rgbIcon__slide1 ;Get the slider axis number
222 LDR R14,rgb__mapping ;Load the mapping number
223 SUB R1,R14,R4 ;Find the table index
224 ADR R14,rgb__writeTbl+2 ;Point to the table
225 LDRB R1,[R14,R1] ;Load the icon number
226 MOV R0,R9 ;Put dialogue handle in R0
227 MOV R2,R3 ;Put slider value in R2
228 BL numWrite_set ;And put it in the icon
229
230 ; --- Now work out what else to update ---
231
232 CMP PC,#0 ;Clear the Z flag
233 BL cs_immediate ;Are we doing immediate ops?
234 LDRCC R14,[R13,#4] ;Load the subreason code
235 CMPCC R14,#slider_sliding ;Is the slider going still?
236 BLNE rgb__zUpdate ;No -- redraw colour square
237
238 BL rgb__xyUpdate ;Now move the crosshair
239
240 90rgb__slChange LDMFD R13!,{R0-R2,R4,PC}^ ;Return to caller
241
242 rgb__writeTbl DCB rgbIcon__writeR
243 DCB rgbIcon__writeG
244 DCB rgbIcon__writeB
245 DCB rgbIcon__writeR
246 DCB rgbIcon__writeG
247
248 ; --- He typed something into one of our icons ---
249
250 rgb__wrChange ROUT
251
252 STMFD R13!,{R0-R5,R14} ;Save some registers
253
254 ; --- First, find the value this writable applies to ---
255
256 CMP R1,#rgbIcon__writeG ;Which writable icon is it?
257 MOVLT R1,#0 ;Red -- remember this map
258 MOVEQ R1,#1 ;Green -- remember this
259 MOVGT R1,#2 ;Blue -- remember this
260 ADR R14,rgb__red ;Point to the mappings
261 LDR R14,[R14,R1,LSL #2] ;Translate the colour
262 LDR R0,[R14,#0] ;Load the actual value
263 SUBS R5,R0,R3 ;Is this our value?
264
265 ; --- He's changed the value -- update slider/colour ---
266
267 STRNE R3,[R14,#0] ;Save the new value away
268 BLNE rgb__colUpdate ;Redraw the colour pot
269 LDR R0,rgb__mapping ;Load the mapping number
270 SUB R3,R1,R0 ;Work out the table index
271 ADR R14,rgb__slideTbl+2 ;Point to slider icon table
272 LDRB R1,[R14,R3] ;Load the icon number
273 LDR R0,cs__modelDb ;Load the panel dialogue
274 BLNE dbx_update ;Redraw the slider nicely
275
276 ; --- Update the main piccy ---
277
278 CMPEQ PC,#0 ;Clear the Z flag
279 BL cs_immediate ;Are we doing immediate ops?
280 CMPCC R2,#numWrite_change ;Is he just typing numbers?
281 BLNE rgb__zUpdate ;No -- redraw colour square
282
283 BL rgb__xyUpdate ;Now move the crosshair
284
285 90rgb__wrChange LDMFD R13!,{R0-R5,PC}^ ;Return to caller
286
287 rgb__slideTbl DCB rgbIcon__slide2
288 DCB rgbIcon__slide1
289 DCB rgbIcon__slide3
290 DCB rgbIcon__slide2
291 DCB rgbIcon__slide1
292
293 rgb__arChange ROUT
294
295 STMFD R13!,{R0-R4,R14} ;Save some registers
296 MOV R4,R2 ;Look after the bump
297
298 ; --- First, find the value this arrow applies to ---
299
300 CMP R1,#rgbIcon__upG ;Which writable icon is it?
301 CMPGT R1,#rgbIcon__downG ;There's two for green
302 MOVLT R3,#0 ;Red -- remember this map
303 MOVEQ R3,#1 ;Green -- remember this
304 MOVGT R3,#2 ;Blue -- remember this
305
306 ; --- Now bump the required writable icon ---
307
308 ADR R14,rgb__writeTbl ;Point to the icon table
309 LDRB R1,[R14,R3] ;Load the correct icon
310 MOV R0,R9 ;Pass dialogue in R0
311 BL numWrite_bump ;Apply the bump value
312
313 ; --- Now perform the update operation ---
314
315 CMPEQ PC,#0 ;Clear the Z flag
316 BL cs_immediate ;Are we doing immediates?
317 TEQCS R4,#0 ;And is the bump sensible?
318 BEQ %90rgb__arChange ;Immediate/end ==> return
319 MOV R3,R2 ;Get value in R3 nicely
320 MOVCS R2,#1 ;Update always if immediate
321 MOVCC R2,#0 ;Default is no update if not
322 TEQ R4,#0 ;And is the bump sensible?
323 MOVEQ R2,#1 ;No -- then force update
324 BL rgb__wrChange ;Handle writable update then
325
326 90rgb__arChange LDMFD R13!,{R0-R4,PC}^ ;And return to caller
327
328 LTORG
329
330 ; --- Close the panel to open a new one ---
331
332 rgb__closePanel ROUT
333
334 STMFD R13!,{R0,R14} ;Save some registers
335 MOV R0,R9 ;Get the dialogue handle
336 BL dbox_destroy ;Kill off the dialogue
337 LDMFD R13!,{R0,PC}^ ;And return to caller
338
339 ; --- Handle a click on one of the WIMP colours ---
340 ;
341 ; The WIMP colour number resides in R14 at the moment :-/
342
343 rgb__wimpCol ROUT
344
345 STMFD R13!,{R0,R1} ;Save some registers
346 SUB R13,R13,#80 ;Make space for palette block
347 MOV R1,R13 ;Point to my block
348 SWI Wimp_ReadPalette ;Read the WIMP palette
349 LDR R1,[R13,R14,LSL #2] ;Load the one we want
350 ADD R13,R13,#80 ;Don't need this now
351
352 ; --- Under RISC OS <3.50, bodge palette entry ---
353 ;
354 ; Because of Acorn stupidity, the ReadPalette values have
355 ; blank lower nibbles. According to Acorn, I must copy the
356 ; top nibbles into the bottom ones for ColourTrans to be
357 ; happy. I assume that this has been sorted out on 3.50 and
358 ; later.
359
360 BL rov_version ;Get the RISC OS version
361 CMP R0,#340 ;It's almost 350 :-)
362 LDRLO R14,=&F0F0F000 ;A nibble mask
363 ANDLO R1,R1,R14 ;Clear bottom nibbles
364 ORRLO R1,R1,R1,LSR #4 ;And duplicate top in bottom
365
366 STR R1,cs__colour+col_rgb ;Save this new colour
367 BL rgb__setValues ;And redo everything nicely
368 LDMFD R13!,{R0,R1,PC}^ ;And return to caller
369
370 LTORG
371
372 ; --- rgb__setValues ---
373 ;
374 ; On entry: R10 == address of colour selector instance data
375 ;
376 ; On exit: --
377 ;
378 ; Use: Updates all the values in the dialogue box from the colour
379 ; word in the workspace (which is assumed to have changed).
380 ; The colour mapping is assumed to still be valid, though.
381
382 rgb__setValues ROUT
383
384 STMFD R13!,{R0-R2,R14} ;Save some registers
385
386 ; --- Unpack the value from the colour RGB word ---
387
388 BL rgb__unpack ;Get the percentages out
389
390 ; --- Do the writable icons ---
391
392 LDR R0,cs__modelDb ;Get the dialogue handle
393 MOV R1,#rgbIcon__writeR ;Get the red writable icon
394 LDR R2,rgb__red ;Find the red value
395 LDR R2,[R2,#0] ;Load the red value
396 BL numWrite_set ;Set it in the icon
397
398 MOV R1,#rgbIcon__writeG ;Get the green writable icon
399 LDR R2,rgb__green ;Find the green value
400 LDR R2,[R2,#0] ;Load the green value
401 BL numWrite_set ;Set it in the icon
402
403 MOV R1,#rgbIcon__writeB ;Get the blue writable icon
404 LDR R2,rgb__blue ;Find the blue value
405 LDR R2,[R2,#0] ;Load the blue value
406 BL numWrite_set ;Set it in the icon
407
408 ; --- Now do the other controls ---
409
410 BL rgb__updateSliders ;Do the slider update
411 BL cs_colChange ;Redraw main colour pot
412 BL rgb__zUpdate ;Force a recache of z
413 BL rgb__xyUpdate ;And a recache of x and y
414 LDMFD R13!,{R0-R2,PC}^ ;And return to caller
415
416 LTORG
417
418 ; --- rgb__updateSliders ---
419 ;
420 ; On entry: R10 == address of colour selector instance data
421 ;
422 ; On exit: --
423 ;
424 ; Use: Redraws all the sliders. Because the slider code is so
425 ; amazingly intelligent, if the values haven't changed, the
426 ; picture you see won't change either.
427
428 rgb__updateSliders ROUT
429
430 STMFD R13!,{R0,R1,R14} ;Save some registers
431 LDR R0,cs__modelDb ;Get the dialogue handle
432 MOV R1,#rgbIcon__slide1 ;Get slider 1's number
433 BL dbx_update ;Redraw it quickly
434 MOV R1,#rgbIcon__slide2 ;Get slider 2's number
435 BL dbx_update ;Redraw it quickly
436 MOV R1,#rgbIcon__slide3 ;Get slider 3's number
437 BL dbx_update ;Redraw it quickly
438 LDMFD R13!,{R0,R1,PC}^ ;And return to caller
439
440 LTORG
441
442 ; --- rgb__setMapping ---
443 ;
444 ; On entry: R0 == rotation number (i.e. which colour is on z azis)
445 ;
446 ; On exit: --
447 ;
448 ; Use: Sets up the workspace so that the dialogue box displays the
449 ; correct mapping.
450
451 rgb__setMapping ROUT
452
453 STMFD R13!,{R0-R3,R14} ;Save some registers
454
455 ; --- Reset the mapping number and table ---
456
457 STR R0,rgb__mapping ;Save the mapping number
458 ADR R1,rgb__mappingTbl ;Point to the table
459 ADD R1,R1,R0 ;Index it nicely
460
461 LDRB R14,[R1],#1 ;Load the blue offset
462 ADD R14,R10,R14 ;Add it to workspace ptr
463 STR R14,rgb__blue ;And store nicely
464 MOV R2,#8 ;The blue slider colour
465 STR R2,[R14,#4] ;Save it in the table
466
467 LDRB R14,[R1],#1 ;Load the green offset
468 ADD R14,R10,R14 ;Add it to workspace ptr
469 STR R14,rgb__green ;And store nicely
470 MOV R2,#10 ;The green slider colour
471 STR R2,[R14,#4] ;Save it in the table
472
473 LDRB R14,[R1],#1 ;Load the red offset
474 ADD R14,R10,R14 ;Add it to workspace ptr
475 STR R14,rgb__red ;And store nicely
476 MOV R2,#11 ;The red slider colour
477 STR R2,[R14,#4] ;Save it in the table
478
479 BL rgb__unpack ;Unpack colour def now
480
481 ; --- Set up the cached values for the diagram ---
482
483 LDR R14,rgb__sl1Val ;Load the x value
484 STR R14,rgb__xPos ;Save it in the cache
485 LDR R14,rgb__sl2Val ;Load the y value
486 STR R14,rgb__yPos ;Save it in the cache
487 LDR R14,rgb__sl3Val ;Load the z value
488 STR R14,rgb__zPos ;Save it in the cache
489
490 LDMFD R13!,{R0-R3,PC}^ ;Return to caller
491
492 LTORG
493
494 ; --- The mapping table ---
495 ;
496 ; The table is done twice, to give it a `wraparound' effect.
497
498 rgb__mappingTbl DCB :INDEX: rgb__sl1Val
499 DCB :INDEX: rgb__sl2Val
500 DCB :INDEX: rgb__sl3Val
501 DCB :INDEX: rgb__sl1Val
502 DCB :INDEX: rgb__sl2Val
503
504 ; --- rgb__unpack ---
505 ;
506 ; On entry: R10 == address of colour selector instance data
507 ;
508 ; On exit: --
509 ;
510 ; Use: Unpacks the colour definition in the cs data into the
511 ; slider values.
512
513 rgb__unpack ROUT
514
515 STMFD R13!,{R0-R2,R14} ;Save some workspace
516 LDR R2,cs__colour+col_rgb ;Get the colour nicely
517
518 ; --- Set up the blue slider ---
519
520 MOV R0,R2,LSR #24 ;Get the blue colour value
521 BL rgb__colToPerC ;Convert it to a percentage
522 LDR R14,rgb__blue ;Load the blue entry address
523 STR R0,[R14] ;Save the blue value in it
524
525 ; --- Now set up the green one ---
526
527 MOV R0,R2,LSR #16 ;Get the green colour value
528 BL rgb__colToPerC ;Convert it to a percentage
529 LDR R14,rgb__green ;Load the green entry address
530 STR R0,[R14] ;Save the green value in it
531
532 ; --- Now set up the red one ---
533
534 MOV R0,R2,LSR #8 ;Get the red colour value
535 BL rgb__colToPerC ;Convert it to a percentage
536 LDR R14,rgb__red ;Load the red entry address
537 STR R0,[R14] ;Save the red value in it
538 LDMFD R13!,{R0-R2,PC}^ ;And return to caller
539
540 LTORG
541
542 ; --- rgb__colToPerC ---
543 ;
544 ; On entry: R0 == colour to convert, from 0 to 255
545 ;
546 ; On exit: R0 == colour as a percentage
547 ;
548 ; Use: Converts a colour to a percentage.
549 ;
550 ; [Generated by Straylight divc]
551 ; Modified by MDW to (a) be unsigned, and (b) round to nearest.
552
553 rgb__colToPerC ROUT
554
555 STMFD R13!,{R1,R14} ;Save some registers
556 AND R0,R0,#&FF ;Mask off any other bits
557 ADD R0,R0,R0,LSL #2 ;Multiply by 5 (x5)
558 ADD R0,R0,R0,LSL #2 ;And by 5 again (x25)
559 MOV R0,R0,LSL #2 ;And now by 4 (x100)
560 MOV R1,R0 ;Keep copy of dividend
561 ADD R0,R0,#127 ;Make it round to nearest
562 ADD R0,R0,R0,LSR #8 ;R0 = R0 x 256/255
563 ADD R0,R0,R0,LSR #16 ;...
564 MOV R0,R0,LSR #8 ;Div by 256 -- R0 = R0 / 255
565 RSB R14,R0,R0,LSL #8 ;Multiply by 255
566 SUB R1,R1,R14 ;Find the difference
567 SUBS R1,R1,#255 ;This is the remainder
568 ADDGE R0,R0,#1 ;If we overshot, bump quot
569 ADDLT R1,R1,#255 ;And chop off remainder
570 LDMFD R13!,{R1,PC}^ ;Return to caller
571
572 LTORG
573
574 ; --- rgb__perCToCol ---
575 ;
576 ; On entry: R0 == colour percentage to convert
577 ;
578 ; On exit: R0 == colour value, from 0-255
579 ;
580 ; Use: Converts a percentage to a colour.
581
582 rgb__perCToCol ROUT
583
584 STMFD R13!,{R1,R14} ;Save some registers
585 RSB R0,R0,R0,LSL #8 ;Multiply it by 255
586 ADD R0,R0,#50 ;Add 50 to round to nearest
587 BL div10 ;Divide by 10
588 BL div10 ;And again (by 100)
589 LDMFD R13!,{R1,PC}^ ;And return to caller
590
591 LTORG
592
593 ; --- rgb__colUpdate ---
594 ;
595 ; On entry: --
596 ;
597 ; On exit: --
598 ;
599 ; Use: Updates the main dialogue's colour pot.
600
601 rgb__colUpdate ROUT
602
603 STMFD R13!,{R0,R2,R14} ;Save some registers
604 MOV R2,#0 ;Clear prospective colour
605
606 LDR R0,rgb__blue ;Get the blue colour address
607 LDR R0,[R0,#0] ;Load the blue percentage
608 BL rgb__perCToCol ;Convert it to a real colour
609 ORR R2,R2,R0,LSL #24 ;Move into R2 nicely
610
611 LDR R0,rgb__green ;Get the green colour address
612 LDR R0,[R0,#0] ;Load the green percentage
613 BL rgb__perCToCol ;Convert it to a real colour
614 ORR R2,R2,R0,LSL #16 ;Move into R2 nicely
615
616 LDR R0,rgb__red ;Get the red colour address
617 LDR R0,[R0,#0] ;Load the red percentage
618 BL rgb__perCToCol ;Convert it to a real colour
619 ORR R2,R2,R0,LSL #8 ;Move into R2 nicely
620
621 STR R2,cs__colour+col_rgb ;Save this as the new colour
622 LDMFD R13!,{R0,R2,R14} ;Restore registers
623 B cs_colChange ;Update the main box's colour
624
625 LTORG
626
627 ; --- rgb__zUpdate ---
628 ;
629 ; On entry: --
630 ;
631 ; On exit: --
632 ;
633 ; Use: Updates everything following a change to the current z
634 ; value. It doesn't change the writable icon, but it does
635 ; most other things.
636
637 rgb__zUpdate ROUT
638
639 STMFD R13!,{R0-R2,R14} ;Save some registers
640
641 ; --- Make sure that the z coordinate changed ---
642
643 LDR R2,rgb__sl3Val ;Load current z slider pos
644 LDR R0,rgb__zPos ;Load the cached position
645 CMP R0,R2 ;Do they match?
646 LDMEQFD R13!,{R0-R2,PC}^ ;Yes -- nothing doing then
647
648 ; --- Remove crosshairs -- it looks nicer ---
649
650 LDR R0,cs__modelDb ;Load the model dialogue
651 MOV R1,#rgbIcon__square ;Get the colour square
652 BL dbx_qUpdate ;Get rid of the crosshair
653
654 ; --- Now recache the x and y coords to prevent flicker ---
655
656 STR R2,rgb__zPos ;Update the cache value
657 LDR R14,rgb__sl1Val ;Load the current x value
658 STR R14,rgb__xPos ;Save it away
659 LDR R14,rgb__sl2Val ;Load the current y value
660 STR R14,rgb__yPos ;Save it away
661
662 ; --- Redraw the main square ---
663
664 BL dbx_update ;Force a redraw of it
665 LDMFD R13!,{R0-R2,PC}^ ;And return to caller
666
667 LTORG
668
669 ; --- rgb__xyUpdate ---
670 ;
671 ; On entry: --
672 ;
673 ; On exit: --
674 ;
675 ; Use: Updates things following a change to either the x or y
676 ; value.
677
678 rgb__xyUpdate ROUT
679
680 STMFD R13!,{R0-R3,R14} ;Save some registers
681 LDR R0,rgb__xPos ;Load cached x position
682 LDR R1,rgb__yPos ;Load cached y position
683 LDR R2,rgb__sl1Val ;And the current x pos
684 LDR R3,rgb__sl2Val ;And the current y pos
685 CMP R0,R2 ;Is the cached x right?
686 CMPEQ R1,R3 ;And is the cached y right?
687 LDMEQFD R13!,{R0-R3,PC}^ ;Yes -- return then
688
689 LDR R0,cs__modelDb ;Load the dialogue box handle
690 MOV R1,#rgbIcon__square ;Load the square icon
691 BL dbx_qUpdate ;Quickly redraw it
692 STR R2,rgb__xPos ;Recache the x position
693 STR R3,rgb__yPos ;Recache the y position
694 BL dbx_qUpdate ;Quickly redraw it
695 LDMFD R13!,{R0-R3,PC}^ ;Return to caller
696
697 LTORG
698
699 ;----- Plotting the colour square -------------------------------------------
700
701 ; --- rgb_plotSquare ---
702 ;
703 ; On entry: R0 == left hand side of colour square to plot
704 ; R1 == bottom edge of colour square to plot
705 ; R2 == which rotation we're plotting
706 ; R3 == x step to plot in
707 ; R4 == y step to plot in
708 ; R5 == z-coordinate value (in 16.16 form)
709 ; R6 == pointer to graphics window block
710 ;
711 ; On exit: --
712 ;
713 ; Use: Plots a cross-section through the RGB colour cube.
714
715 EXPORT rgb_plotSquare
716 rgb_plotSquare ROUT
717
718 STMFD R13!,{R0-R12,R14} ;Save a job-lot of registers
719
720 ; --- Work out the minimum coordinates ---
721
722 LDMIA R6,{R8,R9,R11,R12} ;Load the coordinates out
723 SUB R7,R12,R1 ;Translate max y to relative
724 SUB R12,R9,R1 ;Translate min y too
725 SUB R10,R8,R0 ;Translate min x too
726 SUB R11,R11,R0 ;Translate max x
727
728 ; --- See if we can do really clever things ---
729
730 STMFD R13!,{R0,R11} ;Save our R11 value
731 LDR R11,[R13,#52] ;Load the system R11 value
732 BL screen_getInfo ;Load the screen information
733 MOV R8,R0 ;Look after this address
734 LDMFD R13!,{R0,R11} ;Reload our local value
735 LDR R14,[R8,#screen_bpp] ;Load current bits/pixel
736 CMP R14,#16 ;Is this a 2byte/pixel mode?
737 BEQ rgb__plot32k ;Yes -- branch to special bit
738 CMP R14,#32 ;Is this a 4byte/pixel mode?
739 BEQ rgb__plot16m ;Yes -- branch to special bit
740
741 ; --- Work out rectangle edges ---
742
743 CMP R10,#0 ;Is min x too small?
744 MOVLT R10,#0 ;Yes -- raise it to 0
745 CMP R12,#0 ;Is min y too small?
746 MOVLT R12,#0 ;Yes --- raise that too
747 CMP R11,#255 ;Is the max x too large?
748 MOVGT R11,#255 ;Yes -- reduce it then
749 CMP R7,#255 ;Is the max y too large?
750 MOVGT R7,#255 ;Yes -- reduce it then
751
752 SUB R8,R3,#1 ;Turn the x step to bitmask
753 SUB R9,R4,#1 ;And the same for y step
754 BIC R10,R10,R8 ;Round min x down to step
755 BIC R12,R12,R9 ;And round min y down too
756 BIC R11,R11,R8 ;Round max x down too
757 BIC R7,R7,R9 ;And round down max y
758
759 STMFD R13!,{R7,R10} ;Save rel. min x and max y
760
761 ADD R10,R10,R0 ;Now make min x absolute
762 ADD R12,R12,R1 ;And make min y absolute
763 ADD R11,R11,R0 ;And make max x absolute
764 ADD R7,R7,R1 ;And make max y absolute
765
766 ; --- Now work out the z-value ---
767
768 RSB R5,R5,R5,LSL #8 ;Multiply value by 255
769 ADD R5,R5,#&8000 ;Make sure we round nicely
770 MOV R5,R5,LSR #16 ;And make it 0-255
771
772 ; --- Work out the exclusive rectangle sizes ---
773
774 STMFD R13!,{R11} ;Save our R11 value
775 LDR R11,[R13,#56] ;Load the system R11 value
776 BL screen_getInfo ;Load the screen information
777 LDMFD R13!,{R11} ;Reload our local value
778
779 LDMIA R0,{R8,R9} ;Load the eigen factors out
780 MOV R14,#1 ;This will be shifted around
781 SUB R8,R3,R14,LSL R8 ;Subtract x pixel from x step
782 SUB R9,R4,R14,LSL R9 ;Subtract y pixel from y step
783
784 ; --- Work out all the shift values ---
785
786 CMP R2,#0 ;Is this the red rotation?
787 MOVEQ R0,#24 ;Yes -- then x is blue
788 MOVEQ R1,#16 ;And y is green
789 MOVEQ R5,R5,LSL #8 ;And z is red
790
791 CMP R2,#1 ;Is this the green rotation?
792 MOVEQ R0,#8 ;Yes -- then x is red
793 MOVEQ R1,#24 ;And y is blue
794 MOVEQ R5,R5,LSL #16 ;And z is green
795
796 CMP R2,#2 ;Is this the blue rotation?
797 MOVEQ R0,#16 ;Yes -- then x is green
798 MOVEQ R1,#8 ;And y is red
799 MOVEQ R5,R5,LSL #24 ;And z is blue
800
801 ; --- Set up the initial palette word ---
802
803 LDMFD R13!,{R14} ;Load maximum y palette val
804 ORR R5,R5,R14,LSL R1 ;Fit that into the palette
805
806 LDMFD R13!,{R2} ;Load minimum x palette val
807
808 ; --- Now for the main plotting loop ---
809
810 00 MOV R6,R10 ;Start on the left hand side
811 MOV R14,#255 ;Clear out nasty x palette
812 BIC R5,R5,R14,LSL R0 ;Clear out the right byte
813 ORR R5,R5,R2,LSL R0 ;And set up the min value
814
815 ; --- Plot the rectangle nicely ---
816
817 10 STMFD R13!,{R0-R4} ;Save some registers for this
818
819 ; --- Nothing for it but to use ColourTrans ---
820
821 MOV R0,R5 ;Get the palette entry
822 MOV R3,#&100 ;Please try to dither it
823 MOV R4,#0 ;And have normal GCOL action
824 SWI XColourTrans_SetGCOL ;Try to set the colour up
825 MOVVS R3,#0 ;Try again without dithering
826 MOVVS R0,R5 ;Set the palette word again
827 SWIVS ColourTrans_SetGCOL ;Set the colour the old way
828
829 15 MOV R0,#4 ;Move cursor absolute
830 MOV R1,R6 ;Get the current x coordinate
831 MOV R2,R7 ;And the current y coordinate
832 SWI OS_Plot ;Move the cursor there
833 MOV R0,#97 ;Rectangle fill relative
834 MOV R1,R8 ;Rectangle width thingy
835 MOV R2,R9 ;Rectangle height thingy
836 SWI OS_Plot ;Plot the rectangle
837 LDMFD R13!,{R0-R4} ;Restore a load of registers
838
839 ; --- Now move on to the next square ---
840
841 ADD R6,R6,R3 ;Add on the x increment
842 CMP R6,R11 ;Have we gone too far?
843 ADDLE R5,R5,R3,LSL R0 ;No -- add on the palette val
844 BLE %10rgb_plotSquare ;And go round again
845
846 SUB R7,R7,R4 ;Subtract the y increment
847 CMP R7,R12 ;Have we gone too far?
848 SUBGE R5,R5,R4,LSL R1 ;No -- subtract palette val
849 BGE %00rgb_plotSquare ;And do the next row nicely
850
851 LDMFD R13!,{R0-R12,PC}^ ;Return to caller
852
853 ; --- Fast colour setting routines ---
854
855 20 MOV R1,R5,LSR #8 ;Get hardware colour value
856 MOV R0,#0 ;Set the colour
857 SWI OS_SetColour ;Set the colour really
858 B %15rgb_plotSquare ;And return to main loop
859
860 25 AND R0,R5,#&F800 ;Get the red bits out
861 MOV R1,R0,LSR #11 ;Shift them down
862 AND R0,R5,#&F80000 ;Get the green bits
863 ORR R1,R1,R0,LSR #14 ;Move them in nicely
864 AND R0,R5,#&F8000000 ;Get the blue bits too
865 ORR R1,R1,R0,LSR #17 ;Move them in too
866 MOV R0,#0 ;Set a raw colour
867 SWI OS_SetColour ;Set the colour nicely
868 B %15rgb_plotSquare ;And return to main loop
869
870 30 MOV R14,#3 ;Mask bits off quickly
871 AND R0,R14,R5,LSR #12 ;Get the red bits
872 AND R1,R14,R5,LSR #20 ;Get the green bits
873 AND R2,R14,R5,LSR #28 ;And the blue bits
874 ADD R1,R1,R1,LSL #2 ;Multiply green by 5
875 ADD R2,R2,R0,LSL #1 ;Mult red by 2 and add in
876 ADD R2,R2,R1 ;And add in weighted green
877 MOV R1,R2,LSR #3 ;Get weighted average
878
879 AND R0,R5,#&00C00000 ;Get top two green bits
880 ORR R1,R1,R0,LSR #17 ;Shift into position
881 TST R5,#&00004000 ;Get red bit two
882 ORRNE R1,R1,#&4 ;If set, set in colour
883 TST R5,#&40000000 ;Get blue bit two
884 ORRNE R1,R1,#&8 ;If set, set in colour
885 TST R5,#&00008000 ;Get red bit three
886 ORRNE R1,R1,#&10 ;If set, set in colour
887 TST R5,#&80000000 ;Get blue bit three
888 ORRNE R1,R1,#&80 ;If set, set in colour
889
890 MOV R0,#0 ;Set raw colour
891 SWI OS_SetColour ;Do the colour setting
892 B %15rgb_plotSquare ;And return to main loop
893
894 LTORG
895
896 ; --- rgb__plot32k ---
897 ;
898 ; On entry: R0 == left side of square to plot
899 ; R1 == bottom of square to plot
900 ; R2 == rotation number
901 ; R3 == x step for rectangles
902 ; R4 == y step for rectangles
903 ; R5 == current z-value (in 16.16)
904 ; R6 == pointer to graphics window block
905 ; R7 == unlimited relative max y position to plot
906 ; R8 == pointer to screen info block
907 ; R10 == unlimited relative min x position to plot
908 ; R11 == unlimited relative max x position to plot
909 ; R12 == unlimited relative min y position to plot
910 ; On stack: saved {R0-R12,R14}
911 ;
912 ; On exit: --
913 ;
914 ; Use: Displays an RGB square on the screen at a given location,
915 ; in a 16bpp mode, using direct screen access (TM).
916
917 rgb__plot32k ROUT
918
919 ; --- Prologue: Limit the relative box positions ---
920
921 ADD R8,R8,#screen_dx ;Find the pixel positions
922 LDMIA R8,{R8,R9} ;Load them into registers
923
924 CMP R10,#0 ;Is min x too small?
925 MOVLT R10,#0 ;Yes -- raise it to 0
926 CMP R12,#0 ;Is min y too small?
927 MOVLT R12,#0 ;Yes --- raise that too
928 CMP R11,#256 ;Is the max x too large?
929 MOVGT R11,#256 ;Yes -- reduce it then
930 CMP R7,#256 ;Is the max y too large?
931 MOVGT R7,#256 ;Yes -- reduce it then
932 SUB R11,R11,R8 ;Make this inclusive
933 SUB R7,R7,R9 ;Make this inclusive too
934
935 ; --- Act 1: Find addresses of things on the screen ---
936
937 ADD R9,R0,R10 ;Work out left hand side
938 ADD R8,R1,R7 ;Work out top of area
939 SUB R10,R11,R10 ;Work out width of area
940 SUB R7,R7,R12 ;And the height too
941
942 SUB R12,R9,R0 ;Work out left offset again
943 SUB R11,R8,R1 ;And the top offset too
944
945 SUB R13,R13,#20 ;Space for our vdu vars
946 ADR R0,rgb__vduVars ;Point to the var numbers
947 MOV R1,R13 ;Point to our output block
948 SWI OS_ReadVduVariables ;Get the values nicely
949
950 ; --- Interlude: Set up rectangle sizes ---
951
952 CMP R3,#8 ;Make sure rectangles are >8
953 MOVCC R3,#8 ;If not, make them bigger
954 MOVCC R4,#8 ;(Width and height the same)
955 MOV R14,R3,LSR #3 ;Work out colour increment
956
957 ; --- Reprise: Convert measurements to pixels ---
958
959 LDMIA R13!,{R0,R1} ;Load the x and y eig things
960 MOV R3,R3,LSR R0 ;Convert pixel counters
961 MOV R4,R4,LSR R1 ;Convert other pixel counter
962 MOV R9,R9,LSR R0 ;Convert left hand side
963 MOV R10,R10,LSR R0 ;Convert width of area
964 MOV R7,R7,LSR R1 ;Convert area height
965 MOV R8,R8,LSR R1 ;And the top position
966
967 ; --- Intermission: Pack up pixel counters ---
968 ;
969 ; We pack all this into a word containing the following:
970 ;
971 ; bits 31-24 == x counter reset value
972 ; bits 23-20 == y counter initial value
973 ; bits 19-16 == x counter initial value
974 ; bits 15- 8 == y counter reset value
975 ; bits 7- 0 == colour step value
976 ;
977 ; Can anyone say `Z80 programming techniques'?
978
979 MOV R12,R12,LSR R0 ;Get left offset in pixels
980 SUB R6,R3,#1 ;Get the h pixel count -1
981 AND R0,R12,R6 ;Get the remainder thing
982 SUB R0,R3,R0 ;And get the correct offset
983
984 ORR R3,R4,R3,LSL #16 ;Pack x and y counters
985 ORR R3,R14,R3,LSL #8 ;And move in the colour inc
986
987 RSB R14,R11,#256 ;Get offset from top
988 MOV R11,R11,LSR R1 ;Turn offset into pixels
989 MOV R1,R14,LSR R1 ;Get top offset in pixels
990 SUB R1,R1,#1 ;Subtract one for niceness
991 SUB R6,R4,#1 ;Get the v pixel count -1
992 AND R1,R1,R6 ;Get the remainder thing
993 SUB R1,R4,R1 ;And get the correct offset
994 ORR R0,R0,R1,LSL #4 ;Pack into 1 byte
995
996 ORR R3,R3,R0,LSL #16 ;Put in initial values too
997
998 LDMIA R13!,{R0,R1,R6} ;Load other vdu vars
999 SUB R14,R1,R8 ;Shift origin to top left
1000 MLA R0,R14,R6,R0 ;Work out address of row
1001 ADD R9,R0,R9,LSL #1 ;Work out left address
1002 ADD R8,R9,R10,LSL #1 ;Work out right hand side too
1003
1004 ; --- Act 2: Set up colour information ---
1005
1006 AND R14,R3,#&FF ;Get the colour step value
1007 BIC R10,R3,#&FF ;Move packed init values away
1008
1009 RSB R5,R5,R5,LSL #8 ;Multiply z value by 255
1010 MOV R5,R5,LSR #19 ;And make it 0-31
1011
1012 AND R3,R10,#&FF000000 ;Get the x pixel count reinit
1013 SUB R3,R3,#&01000000 ;Turn it into a bitmask
1014 BIC R3,R12,R3,LSR #24 ;Round colour down nicely
1015 LDR R12,[R13,#-20] ;Get the xeig factor
1016 MOV R3,R3,LSL R12 ;Shift colour up to OS units
1017 MOV R3,R3,LSR #3 ;Get the x colour in 0-31
1018
1019 AND R4,R10,#&0000FF00 ;Get the y pixel count reinit
1020 SUB R4,R4,#&00000100 ;Turn it into a bitmask
1021 BIC R4,R11,R4,LSR #8 ;Round colour down nicely
1022 LDR R11,[R13,#-16] ;Get the yeig factor
1023 MOV R4,R4,LSL R11 ;Shift colour up to OS units
1024 MOV R4,R4,LSR #3 ;And the y one too please
1025
1026 MOV R12,#&1F ;This is a useful value
1027
1028 CMP R2,#0 ;Is this the red rotation?
1029 MOVEQ R0,R5,LSL #16 ;Build the colour up...
1030 ORREQ R0,R0,R4,LSL #21 ;Still doing that...
1031 ORREQ R0,R0,R3,LSL #26 ;Almost finished now...
1032 MOVEQ R1,R3,LSL #26 ;And the x-init value
1033 MOVEQ R3,R14,LSL #21 ;Get the y increment right
1034 MOVEQ R4,R14,LSL #26 ;And the x increment
1035 MOVEQ R5,R12,LSL #26 ;Get the x-clear mask
1036
1037 CMP R2,#1 ;Is this the green rotation?
1038 MOVEQ R0,R3,LSL #16 ;Build the colour up...
1039 ORREQ R0,R0,R5,LSL #21 ;Still doing that...
1040 ORREQ R0,R0,R4,LSL #26 ;Almost finished now...
1041 MOVEQ R1,R3,LSL #16 ;And the x-init value
1042 MOVEQ R3,R14,LSL #26 ;Get the y increment right
1043 MOVEQ R4,R14,LSL #16 ;And the x increment
1044 MOVEQ R5,R12,LSL #16 ;Get the x-clear mask
1045
1046 CMP R2,#2 ;Is this the blue rotation?
1047 MOVEQ R0,R4,LSL #16 ;Build the colour up...
1048 ORREQ R0,R0,R3,LSL #21 ;Still doing that...
1049 ORREQ R0,R0,R5,LSL #26 ;Almost finished now...
1050 MOVEQ R1,R3,LSL #21 ;Get the x-init value
1051 MOVEQ R3,R14,LSL #16 ;Get the y increment right
1052 MOVEQ R4,R14,LSL #21 ;And the x increment
1053 MOVEQ R5,R12,LSL #21 ;Get the x-clear mask
1054
1055 ; --- Act 3. Initialise the pixel counts ---
1056
1057 MOV R14,#&F ;For reading nibbles
1058 AND R12,R14,R10,LSR #16 ;Get the initial x value
1059 AND R2,R14,R10,LSR #20 ;Get the initial y value too
1060 ORR R2,R10,R2 ;Put that into the count reg
1061 SWI OS_EnterOS ;Avoid problems with PhysMem
1062
1063 ; --- Act 4. Plot the bloody thing ---
1064
1065 10rgb__plot32k MOV R10,R9 ;Get the current address
1066 MOV R11,#0 ;Clear the buffer value
1067 STMFD R13!,{R12} ;Save the x count value
1068
1069 ; --- Start plotting this row ---
1070
1071 TST R10,#2 ;Is this address aligned?
1072 BEQ %20rgb__plot32k ;Yes -- start at main loop
1073 LDR R14,[R10,#-2] ;No -- load word from here
1074 MOV R14,R14,LSL #16 ;Shift all the way up
1075 ORR R14,R0,R14,LSR #16 ;Build the replacement word
1076 STR R14,[R10,#-2] ;And store in frame buffer
1077 B %25rgb__plot32k ;Jump to end of loop
1078
1079 ; --- Main row plotting loop (time critical :-) ) ---
1080
1081 20rgb__plot32k ORR R11,R0,R11,LSR #16 ;Add colour into buffer
1082 TST R10,#2 ;Is this an odd address?
1083 STRNE R11,[R10,#-2] ;Yes -- done both halfwords
1084
1085 25rgb__plot32k ADD R10,R10,#2 ;Move on to next pixel
1086 CMP R10,R8 ;Have we finished yet?
1087 BHI %30rgb__plot32k ;No -- do the rest then
1088 SUBS R12,R12,#1 ;Decrement pixel counter
1089 ADDEQ R0,R0,R4 ;If cleared, add on colour
1090 MOVEQ R12,R2,LSR #24 ;And reinitialise counter
1091 B %20rgb__plot32k ;Go round for more
1092
1093 ; --- We've finished; do we have a halfword left over? ---
1094
1095 30rgb__plot32k TST R10,#2 ;Is the address odd?
1096 LDRNE R14,[R10,#-2] ;Yes -- read the old word
1097 MOVNE R11,R11,LSR #16 ;Get buffer value in low hw
1098 MOVNE R14,R14,LSR #16 ;Get screen value in low hw
1099 ORRNE R14,R11,R14,LSL #16 ;Build correct word to write
1100 STRNE R14,[R10,#-2] ;Store this word away
1101
1102 ; --- Now move on to the next row ---
1103
1104 LDMFD R13!,{R12} ;Unstack initial x counter
1105 ADD R9,R9,R6 ;Move start address down 1
1106 ADD R8,R8,R6 ;Move end address down 1
1107 BIC R0,R0,R5 ;Clear the x colour section
1108 ORR R0,R0,R1 ;Reintialise the x colour
1109 SUB R2,R2,#1 ;Decrement y counter
1110 TST R2,#&FF ;Is it now zero?
1111 BICEQ R2,R2,#&00FF0000 ;Clear unused byte in word
1112 ORREQ R2,R2,R2,LSR #8 ;Yes -- reinitialise
1113 SUBEQ R0,R0,R3 ;And increment the y colour
1114 SUBS R7,R7,#1 ;Decrement scan line counter
1115 BCS %10rgb__plot32k ;And go back up again
1116
1117 TEQP PC,#0 ;Return to user mode
1118 MOV R0,R0 ;Keep ARM ecstatically happy
1119 LDMFD R13!,{R0-R12,PC}^ ;Return to caller
1120
1121 rgb__vduVars DCD 4,5 ;X and Y eigen factors
1122 DCD 149 ;Start of display memory
1123 DCD 12 ;How high is the screen
1124 DCD 6 ;Width of scan line in pixels
1125 DCD -1
1126
1127 LTORG
1128
1129 ; --- rgb__plot16m ---
1130 ;
1131 ; On entry: R0 == left side of square to plot
1132 ; R1 == bottom of square to plot
1133 ; R2 == rotation number
1134 ; R3 == x step for rectangles
1135 ; R4 == y step for rectangles
1136 ; R5 == current z-value (in 16.16)
1137 ; R6 == pointer to graphics window block
1138 ; R7 == unlimited relative max y position to plot
1139 ; R8 == pointer to screen info block
1140 ; R10 == unlimited relative min x position to plot
1141 ; R11 == unlimited relative max x position to plot
1142 ; R12 == unlimited relative min y position to plot
1143 ; On stack: saved {R0-R12,R14}
1144 ;
1145 ; On exit: --
1146 ;
1147 ; Use: Displays an RGB square on the screen at a given location,
1148 ; in a 32bpp mode, using direct screen access (TM).
1149
1150 rgb__plot16m ROUT
1151
1152 ; --- Prologue: Limit the relative box positions ---
1153
1154 ADD R8,R8,#screen_dx ;Find the pixel positions
1155 LDMIA R8,{R8,R9} ;Load them into registers
1156
1157 CMP R10,#0 ;Is min x too small?
1158 MOVLT R10,#0 ;Yes -- raise it to 0
1159 CMP R12,#0 ;Is min y too small?
1160 MOVLT R12,#0 ;Yes --- raise that too
1161 CMP R11,#256 ;Is the max x too large?
1162 MOVGT R11,#256 ;Yes -- reduce it then
1163 CMP R7,#256 ;Is the max y too large?
1164 MOVGT R7,#256 ;Yes -- reduce it then
1165 SUB R11,R11,R8 ;Make this inclusive
1166 SUB R7,R7,R9 ;Make this inclusive too
1167
1168 ; --- Act 1: Find addresses of things on the screen ---
1169
1170 ADD R9,R0,R10 ;Work out left hand side
1171 ADD R8,R1,R7 ;Work out top of area
1172 SUB R10,R11,R10 ;Work out width of area
1173 SUB R7,R7,R12 ;And the height too
1174
1175 SUB R12,R9,R0 ;Work out left offset again
1176 SUB R11,R8,R1 ;And the top offset too
1177
1178 SUB R13,R13,#20 ;Space for our vdu vars
1179 ADR R0,rgb__vduVars ;Point to the var numbers
1180 MOV R1,R13 ;Point to our output block
1181 SWI OS_ReadVduVariables ;Get the values nicely
1182
1183 ; --- Reprise: Convert measurements to pixels ---
1184
1185 LDMIA R13!,{R0,R1} ;Load the x and y eig things
1186 MOV R3,R3,LSR R0 ;Convert pixel counters
1187 MOV R4,R4,LSR R1 ;Convert other pixel counter
1188 MOV R9,R9,LSR R0 ;Convert left hand side
1189 MOV R10,R10,LSR R0 ;Convert width of area
1190 MOV R7,R7,LSR R1 ;Convert area height
1191 MOV R8,R8,LSR R1 ;And the top position
1192
1193 ; --- Intermission: Pack up pixel counters ---
1194 ;
1195 ; We pack all this into a word containing the following:
1196 ;
1197 ; bits 31-24 == x counter reset value
1198 ; bits 23-20 == y counter initial value
1199 ; bits 19-16 == x counter initial value
1200 ; bits 15- 8 == y counter reset value
1201 ; bits 7- 0 == colour step value
1202 ;
1203 ; Can anyone say `Z80 programming techniques'?
1204
1205 MOV R12,R12,LSR R0 ;Get left offset in pixels
1206 SUB R6,R3,#1 ;Get the h pixel count -1
1207 AND R0,R12,R6 ;Get the remainder thing
1208 SUB R0,R3,R0 ;And get the correct offset
1209
1210 ORR R3,R4,R3,LSL #16 ;Pack x and y counters
1211 MOV R3,R3,LSL #8 ;Move that up one byte
1212
1213 RSB R14,R11,#256 ;Get offset from top
1214 MOV R11,R11,LSR R1 ;Turn offset into pixels
1215 MOV R1,R14,LSR R1 ;Get top offset in pixels
1216 SUB R1,R1,#1 ;Subtract one for niceness
1217 SUB R6,R4,#1 ;Get the v pixel count -1
1218 AND R1,R1,R6 ;Get the remainder thing
1219 SUB R1,R4,R1 ;And get the correct offset
1220 ORR R0,R0,R1,LSL #4 ;Pack into 1 byte
1221
1222 ORR R3,R3,R0,LSL #16 ;Put in initial values too
1223
1224 LDMIA R13!,{R0,R1,R6} ;Load other vdu vars
1225 SUB R14,R1,R8 ;Shift origin to top left
1226 MLA R0,R14,R6,R0 ;Work out address of row
1227 ADD R9,R0,R9,LSL #2 ;Work out left address
1228 ADD R8,R9,R10,LSL #2 ;Work out right hand side too
1229
1230 ; --- Act 2: Set up colour information ---
1231
1232 BIC R10,R3,#&FF ;Move packed init values away
1233
1234 RSB R5,R5,R5,LSL #8 ;Multiply z value by 255
1235 MOV R5,R5,LSR #16 ;And make it 0-255
1236
1237 AND R3,R10,#&FF000000 ;Get the x pixel count reinit
1238 SUB R3,R3,#&01000000 ;Turn it into a bitmask
1239 BIC R3,R12,R3,LSR #24 ;Round colour down nicely
1240 LDR R12,[R13,#-20] ;Get the xeig factor
1241 MOV R3,R3,LSL R12 ;Shift colour up to OS units
1242 AND R14,R10,#&FF000000 ;Get the x reinit value
1243 MOV R14,R14,LSR #24 ;Bring it down to earth
1244 MOV R14,R14,LSL R12 ;And turn into OS units
1245
1246 AND R4,R10,#&0000FF00 ;Get the y pixel count reinit
1247 SUB R4,R4,#&00000100 ;Turn it into a bitmask
1248 BIC R4,R11,R4,LSR #8 ;Round colour down nicely
1249 LDR R12,[R13,#-16] ;Get the yeig factor
1250 MOV R4,R4,LSL R12 ;Shift colour up to OS units
1251 AND R11,R10,#&0000FF00 ;Get the y reinit value
1252 MOV R11,R11,LSR #8 ;Bring it down to earth
1253 MOV R11,R11,LSL R12 ;And turn into OS units
1254
1255 MOV R12,#&FF ;This is a useful value
1256
1257 CMP R2,#0 ;Is this the red rotation?
1258 MOVEQ R0,R5,LSL #0 ;Build the colour up...
1259 ORREQ R0,R0,R4,LSL #8 ;Still doing that...
1260 ORREQ R0,R0,R3,LSL #16 ;Almost finished now...
1261 MOVEQ R1,R3,LSL #16 ;And the x-init value
1262 MOVEQ R3,R11,LSL #8 ;Get the y increment right
1263 MOVEQ R4,R14,LSL #16 ;And the x increment
1264 MOVEQ R5,R12,LSL #16 ;Get the x-clear mask
1265
1266 CMP R2,#1 ;Is this the green rotation?
1267 MOVEQ R0,R3,LSL #0 ;Build the colour up...
1268 ORREQ R0,R0,R5,LSL #8 ;Still doing that...
1269 ORREQ R0,R0,R4,LSL #16 ;Almost finished now...
1270 MOVEQ R1,R3,LSL #0 ;And the x-init value
1271 MOVEQ R3,R11,LSL #16 ;Get the y increment right
1272 MOVEQ R4,R14,LSL #0 ;And the x increment
1273 MOVEQ R5,R12,LSL #0 ;Get the x-clear mask
1274
1275 CMP R2,#2 ;Is this the blue rotation?
1276 MOVEQ R0,R4,LSL #0 ;Build the colour up...
1277 ORREQ R0,R0,R3,LSL #8 ;Still doing that...
1278 ORREQ R0,R0,R5,LSL #16 ;Almost finished now...
1279 MOVEQ R1,R3,LSL #8 ;Get the x-init value
1280 MOVEQ R3,R11,LSL #0 ;Get the y increment right
1281 MOVEQ R4,R14,LSL #8 ;And the x increment
1282 MOVEQ R5,R12,LSL #8 ;Get the x-clear mask
1283
1284 ; --- Act 3. Initialise the pixel counts ---
1285
1286 MOV R14,#&F ;For reading nibbles
1287 AND R12,R14,R10,LSR #16 ;Get the initial x value
1288 AND R2,R14,R10,LSR #20 ;Get the initial y value too
1289 ORR R2,R10,R2 ;Put that into the count reg
1290
1291 ; --- Act 4. Plot the bloody thing ---
1292
1293 SWI OS_EnterOS ;Avoid problems with PhysMem
1294
1295 10rgb__plot16m MOV R10,R9 ;Get the current address
1296 MOV R11,R12 ;Initialise the x counter
1297
1298 ; --- Main row plotting loop (time critical :-) ) ---
1299
1300 20rgb__plot16m STR R0,[R10],#4 ;Store this pixel
1301
1302 25rgb__plot16m CMP R10,R8 ;Have we finished yet?
1303 BHI %30rgb__plot16m ;No -- do the rest then
1304 SUBS R11,R11,#1 ;Decrement pixel counter
1305 ADDEQ R0,R0,R4 ;If cleared, add on colour
1306 MOVEQ R11,R2,LSR #24 ;And reinitialise counter
1307 B %20rgb__plot16m ;Go round for more
1308
1309 ; --- We've finished; move on to next row ---
1310
1311 30rgb__plot16m ADD R9,R9,R6 ;Move start address down 1
1312 ADD R8,R8,R6 ;Move end address down 1
1313 BIC R0,R0,R5 ;Clear the x colour section
1314 ORR R0,R0,R1 ;Reintialise the x colour
1315 SUB R2,R2,#1 ;Decrement y counter
1316 TST R2,#&FF ;Is it now zero?
1317 BICEQ R2,R2,#&00FF0000 ;Clear unused byte in word
1318 ORREQ R2,R2,R2,LSR #8 ;Yes -- reinitialise
1319 SUBEQ R0,R0,R3 ;And increment the y colour
1320 SUBS R7,R7,#1 ;Decrement scan line counter
1321 BCS %10rgb__plot16m ;And go back up again
1322
1323 TEQP PC,#0 ;Return to user mode
1324 MOV R0,R0 ;Keep ARM ecstatically happy
1325 LDMFD R13!,{R0-R12,PC}^ ;Return to caller
1326
1327 LTORG
1328
1329 ; --- rgb__plotHair ---
1330 ;
1331 ; On entry: R2 == x coordinate of cross
1332 ; R3 == y coordinate of cross
1333 ;
1334 ; On exit: --
1335 ;
1336 ; Use: Plots the crosshair on an RGB colour square to mark the
1337 ; current position nicely.
1338
1339 rgb__plotHair ROUT
1340
1341 STMFD R13!,{R0-R3,R14} ;Save some registers
1342 MOV R0,#4 ;Move cursor absolute
1343 MOV R1,R2 ;Get the x coordinate
1344 SUB R2,R3,#256 ;Move down a little bit
1345 SWI OS_Plot ;Move the cursor there
1346 MOV R0,#2 ;Plot in logical inverse (!)
1347 MOV R1,#0 ;No x movement please
1348 MOV R2,#512 ;And plot upwards
1349 SWI OS_Plot ;Plot the vertical line
1350
1351 MOV R0,#0 ;Move cursor relative
1352 MOV R1,#-256 ;Move back a bit
1353 MOV R2,#-256 ;Move down a bit
1354 SWI OS_Plot ;Move the cursor there
1355 MOV R0,#2 ;Plot in logical inverse (!)
1356 MOV R1,#512 ;Plot the cross beam
1357 MOV R2,#0 ;No y movement please
1358 SWI OS_Plot ;Plot the horizontal line
1359
1360 MOV R0,#0 ;Move cursor relative
1361 MOV R1,#-256 ;Move back a bit
1362 MOV R2,#0 ;Move back to centre
1363 SWI OS_Plot ;Move the cursor there
1364 MOV R0,#146 ;Circle relative
1365 MOV R1,#16 ;Radius 16
1366 MOV R2,#0 ;Don't screw up calculation
1367 SWI OS_Plot ;Plot the circle
1368
1369 LDMFD R13!,{R0-R3,PC}^ ;And return to caller
1370
1371 LTORG
1372
1373 ;----- Custom dbx controls --------------------------------------------------
1374
1375 ; --- rgbSquare ---
1376
1377 rgbSquare ROUT
1378
1379 DCD 0,0
1380 DCD dbxMask_redraw + dbxMask_update + dbxMask_click
1381
1382 CMP R0,#dbxEvent_update ;Is it an update event?
1383 BEQ %10rgbSquare ;Yes -- handle it
1384 CMP R0,#dbxEvent_click ;Is it a click event?
1385 BEQ %20rgbSquare ;Yes -- handle it
1386
1387 ; --- Deal with a redraw event ---
1388
1389 STMFD R13!,{R0-R6,R10,R14} ;Save some registers
1390 MOV R10,R8 ;Get dbox data in R10
1391 STMFD R13!,{R2,R3} ;Save bottom left corner
1392
1393 ; --- Sort out the resolution ---
1394
1395 BL cs_resolution ;Get the current resolution
1396 CMP R0,#0 ;Is it pixel-level?
1397 BLEQ screen_getInfo ;Yes -- get screen info
1398 ADDEQ R0,R0,#screen_dx ;Point to the pixel size
1399 LDMEQIA R0,{R3,R4} ;And load the values
1400 ADRNE R14,rgb__resTable ;Otherwise point at the table
1401 ADDNE R14,R14,R0 ;Find the correct entry
1402 LDRNEB R3,[R14,#0] ;Load the square size
1403 MOVNE R4,R3 ;And do it in both directions
1404
1405 ; --- Sort out the z value too ---
1406
1407 LDR R0,rgb__zPos ;Get the z slider value
1408 MOV R0,R0,LSL #16 ;Convert to 16.16 form
1409 ADD R0,R0,#50 ;Make it round to nearest
1410 BL div10 ;Divide it by 10
1411 BL div10 ;And again -- div by 100
1412 MOV R5,R0 ;This is the z coordinate
1413
1414 ; --- Call the main plot code ---
1415
1416 LDMFD R13!,{R0,R1} ;Load the bottom left corner
1417 LDR R2,rgb__mapping ;Get the colour mapping
1418 BL rgb_plotSquare ;Do the plotting
1419 LDMFD R13!,{R0-R6,R10,R14} ;Drop through to update code
1420
1421 ; --- Plot the crosshair as part of update ---
1422
1423 10rgbSquare STMFD R13!,{R0-R5,R10,R14} ;Save some registers
1424 MOV R10,R8 ;Find my workspace address
1425 SUB R4,R4,R2 ;Get the icon width
1426 SUB R5,R5,R3 ;And the height
1427 LDR R0,rgb__xPos ;Load cached x position
1428 MUL R0,R4,R0 ;Scale it to the width
1429 ADD R0,R0,#50 ;Round to nearest on divide
1430 BL div10 ;And divide down
1431 BL div10 ;And divide down again
1432 ADD R2,R2,R0 ;Find the x cross position
1433 LDR R0,rgb__yPos ;Load cached y position
1434 MUL R0,R5,R0 ;Scale it to the height
1435 ADD R0,R0,#50 ;Round to nearest on divide
1436 BL div10 ;And divide down
1437 BL div10 ;And divide down again
1438 ADD R3,R3,R0 ;Find the y cross position
1439 BL rgb__plotHair ;Plot the crosshair nicely
1440 LDMFD R13!,{R0-R5,R10,PC}^ ;And return to caller
1441
1442 rgb__resTable DCB 0,4,8,16
1443
1444 ; --- Handle click events on the square ---
1445
1446 20rgbSquare TST R2,#5 ;Is it a real button click?
1447 MOVEQS PC,R14 ;No -- ignore it then
1448 STMFD R13!,{R0-R5,R10,R14} ;Save some registers
1449
1450 ; --- Start the drag operation ---
1451
1452 MOV R0,R10 ;Get dialogue handle
1453 BL dbx_controlBBox ;Get the bonding box nicely
1454 BL dbox_window ;Get the window handle
1455 MOV R1,#7 ;User drag type
1456 SUB R13,R13,#56 ;Make a drag box on the stack
1457 STMIA R13,{R0,R1} ;Save them away nicely
1458 ADD R14,R13,#24 ;Point to parent box
1459 STMIA R14,{R2-R5} ;Save the bounding box here
1460 MOV R1,R13 ;Point to my block
1461 SWI Wimp_DragBox ;Set up the drag nicely
1462 ADD R13,R13,#56 ;Reclaim the stack space
1463
1464 ; --- Set up the handlers nicely ---
1465
1466 MOV R10,R8 ;Point to dbox data in R10
1467 ADR R0,rgb__ukEvents ;Point to unknown handler
1468 MOV R1,#0 ;Don't care about R4
1469 MOV R2,R10 ;Pass dbox data in R10
1470 MOV R3,R12 ;Pass workspace in R12
1471 BL win_unknownHandler ;Register the handler
1472 MOVVC R0,#2 ;Call every TV frame
1473 ADRVC R1,rgb__idles ;Point to the idle handler
1474 BLVC idle_handler ;Register that too
1475 BL rgb__idles ;Call idle handler now
1476 LDMFD R13!,{R0-R5,R10,PC}^ ;Return to caller
1477
1478 LTORG
1479
1480 ; --- rgb__idles ---
1481 ;
1482 ; On entry: --
1483 ;
1484 ; On exit: --
1485 ;
1486 ; Use: Handles idle events during a drag in the colour square.
1487
1488 rgb__idles ROUT
1489
1490 STMFD R13!,{R0-R5,R10,R14} ;Save some registers
1491 LDR R0,cs__modelDb ;Get the dialogue box
1492 MOV R1,#rgbIcon__square ;Get my icon handle
1493 BL dbx_controlBBox ;Get my bounding box nicely
1494 SUB R13,R13,#20 ;Get a pointer block
1495 MOV R1,R13 ;Point at it nicely
1496 SWI Wimp_GetPointerInfo ;Find the pointer posn
1497 LDMIA R13,{R0,R1} ;Load pointer coordinates
1498 ADD R13,R13,#20 ;Recover that block
1499
1500 ; --- Work out the new cross position ---
1501
1502 SUB R4,R4,R2 ;Work out the icon width
1503 SUB R5,R5,R3 ;And the icon height
1504 SUB R2,R0,R2 ;Work out the x offset
1505 SUB R3,R1,R3 ;And the y offset
1506
1507 ADD R2,R2,R2,LSL #2 ;Multiply x by 5
1508 ADD R2,R2,R2,LSL #2 ;Multiply x by 5 (x25)
1509 MOV R2,R2,LSL #2 ;Multiply x by 4 (x100)
1510
1511 ADD R3,R3,R3,LSL #2 ;Multiply y by 5
1512 ADD R3,R3,R3,LSL #2 ;Multiply y by 5 (x25)
1513 MOV R3,R3,LSL #2 ;Multiply y by 4 (x100)
1514
1515 MOV R0,R2 ;Get the x value
1516 MOV R1,R4 ;And the icon width
1517 BL div_round ;Divide to get percentage
1518 STR R0,rgb__sl1Val ;Save the x position
1519
1520 MOV R0,R3 ;Get the y value
1521 MOV R1,R5 ;And the icon height
1522 BL div_round ;Divide to get percentage
1523 STR R0,rgb__sl2Val ;Save the y position
1524
1525 BL rgb__xyUpdate ;Redraw crosshairs if reqd
1526 LDR R0,cs__modelDb ;Get the dialogue handle
1527 MOV R1,#rgbIcon__slide1 ;Get slider 1's number
1528 BL dbx_update ;Redraw it quickly
1529 MOV R1,#rgbIcon__slide2 ;Get slider 2's number
1530 BL dbx_update ;Redraw it quickly
1531 BL rgb__colUpdate ;Redraw the colour button
1532
1533 ; --- Now update the correct icons ---
1534
1535 ADRL R5,rgb__writeTbl+2 ;Point to icon number table
1536 LDR R14,rgb__mapping ;And get the current mappiing
1537 ADD R5,R5,R14 ;Find the correct entry
1538
1539 LDRB R1,[R5,#0] ;Load the x icon
1540 LDR R2,rgb__sl1Val ;Get the new x value
1541 BL numWrite_set ;Put it in the icon
1542 LDRB R1,[R5,#-1] ;Load the y icon
1543 LDR R2,rgb__sl2Val ;Get the new y value
1544 BL numWrite_set ;Put it in the icon
1545 LDMFD R13!,{R0-R5,R10,PC}^ ;And return to caller
1546
1547 LTORG
1548
1549 ; --- rgb__ukEvents ---
1550 ;
1551 ; On entry: R0 == event code
1552 ;
1553 ; On exit: CS if handled
1554 ;
1555 ; Use: Handles unknown events during a drag in the RGB colour
1556 ; square.
1557
1558 rgb__ukEvents ROUT
1559
1560 CMP R0,#7 ;Is it a drag over event?
1561 MOVNES PC,R14 ;No -- then return to caller
1562 STMFD R13!,{R0-R3,R14} ;Save some registers
1563 BL rgb__idles ;Get one last drag position
1564 ADR R0,rgb__ukEvents ;Point to unknown handler
1565 MOV R1,#0 ;Don't care about R4
1566 MOV R2,R10 ;Pass dbox data in R10
1567 MOV R3,R12 ;Pass workspace in R12
1568 BL win_removeUnknownHandler ;Deregister the handler
1569 MOVVC R0,#2 ;Call every TV frame
1570 ADRVC R1,rgb__idles ;Point to the idle handler
1571 BLVC idle_removeHandler ;Deregister that too
1572 LDMFD R13!,{R0-R3,PC}^ ;And return to caller
1573
1574 LTORG
1575
1576 ;----- Icon numbers ---------------------------------------------------------
1577
1578 rgbIcon__square EQU 0 ;The main colour square
1579 rgbIcon__slide1 EQU 1 ;The x slider (slider 1)
1580 rgbIcon__slide2 EQU 2 ;The y slider (slider 2)
1581 rgbIcon__slide3 EQU 3 ;The z slider (slider 3)
1582
1583 rgbIcon__radioR EQU 4 ;The `Red' radio button
1584 rgbIcon__writeR EQU 5 ;The `Red' writable area
1585 rgbIcon__upR EQU 6 ;The `Red' up arrow button
1586 rgbIcon__downR EQU 7 ;The `Red' down arrow button
1587
1588 rgbIcon__radioG EQU 9 ;The `Green' radio button
1589 rgbIcon__writeG EQU 10 ;The `Green' writable area
1590 rgbIcon__upG EQU 11 ;The `Green' up arrow button
1591 rgbIcon__downG EQU 12 ;The `Green' down arrow buttn
1592
1593 rgbIcon__radioB EQU 14 ;The `Blue' radio button
1594 rgbIcon__writeB EQU 15 ;The `Blue' writable area
1595 rgbIcon__upB EQU 16 ;The `Blue' up arrow button
1596 rgbIcon__downB EQU 17 ;The `Blue' down arrow button
1597
1598 rgbIcon__wCols EQU 20 ;Base of the WIMP colours
1599
1600 ;----- That's all, folks ----------------------------------------------------
1601
1602 END