; ; rgb.s ; ; Handling the RGB colour model dialogue box ; ; © 1994 Straylight ; ;----- Standard header ------------------------------------------------------ GET libs:header GET libs:swis GET libs:stream ;----- External dependencies ------------------------------------------------ GET sapphire:dbox GET sapphire:divide GET sapphire:idle GET sapphire:roVersion GET sapphire:screen GET sapphire:win GET sapphire:dbx.dbx GET sapphire:dbx.arrow GET sapphire:dbx.numWrite GET sapphire:dbx.slider GET sapphire:_cs.kernel GET sapphire:_cs.vars ;----- Main code ------------------------------------------------------------ AREA |Sapphire$$Code|,CODE,READONLY ; --- rgb_open --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Called by the colour picker EXPORT rgb_open rgb_open ROUT STMFD R13!,{R1-R3,R14} ;Stack the link register ADR R0,rgb__dbName ;Point to dialogue box name BL dbox_create ;Create the dialogue box LDMVSFD R13!,{R1-R3,PC} ;Return now if it failed STR R0,[R13,#-4]! ;Return dialogue handle in R0 ; --- Attach event handlers and things --- ADR R1,rgb__dbHandler ;Point to my handler code MOV R2,R10 ;Pass colour workspace in R10 MOV R3,R12 ;Pass my workspace in R12 BL dbox_eventHandler ;Register my event handler ADR R1,rgb__dbxDef ;Point to the control defn BL dbx_declare ;Declare it to dbx nicely ; --- Set up the workspace --- MOV R0,#0 ;Set the Red mapping BL rgb__setMapping ;Set this as the mapping ; --- Set up the dialogue box --- LDR R0,[R13,#0] ;Load the dialogue handle LDR R1,rgb__mapping ;Get the current mapping ADD R1,R1,R1,LSL #2 ;Multiply by icon offset (5) ADD R1,R1,#rgbIcon__radioR ;Add on to get icon number MOV R2,#1 ;Please select this icon BL dbox_select ;Select the right one MOV R1,#rgbIcon__writeR ;Get the red writable icon LDR R2,rgb__red ;Find the red value LDR R2,[R2,#0] ;Load the red value BL numWrite_set ;Set it in the icon MOV R1,#rgbIcon__writeG ;Get the green writable icon LDR R2,rgb__green ;Find the green value LDR R2,[R2,#0] ;Load the green value BL numWrite_set ;Set it in the icon MOV R1,#rgbIcon__writeB ;Get the blue writable icon LDR R2,rgb__blue ;Find the blue value LDR R2,[R2,#0] ;Load the blue value BL numWrite_set ;Set it in the icon LDMFD R13!,{R0-R3,R14} ;Return to caller rgb__dbName DCB "rgb",0 rgb__dbxDef CONTROL rgbIcon__square,rgbSquare,R10,0,0 ECTRL SLIDER rgbIcon__slide1,R10,:INDEX: rgb__sl1Val, slFlag_horizontal + slFlag_colData,0,0,1,100 NUMWRT rgbIcon__writeR,0,100 ARROW rgbIcon__upR,1 ARROW rgbIcon__downR,-1 SLIDER rgbIcon__slide2,R10,:INDEX: rgb__sl2Val, slFlag_vertical + slFlag_colData,0,0,1,100 NUMWRT rgbIcon__writeG,0,100 ARROW rgbIcon__upG,1 ARROW rgbIcon__downG,-1 SLIDER rgbIcon__slide3,R10,:INDEX: rgb__sl3Val, slFlag_vertical + slFlag_colData,0,0,1,100 NUMWRT rgbIcon__writeB,0,100 ARROW rgbIcon__upB,1 ARROW rgbIcon__downB,-1 DBXEND ; --- rgb__dbHandler --- ; ; On entry: R0 == dialogue box event code ; R1-R7 == depend on the event ; R9 == dialogue box handle of RGB panel ; R10 == pointer to colour selector workspace ; R12 == nothing much ; ; On exit: -- ; ; Use: Handles events for the RGB panel. rgb__dbHandler ROUT ; --- Dispatch events to their destinations --- CMP R0,#rgbIcon__radioR ;Is it the red view button? CMPNE R0,#rgbIcon__radioG ;Or the green view button? CMPNE R0,#rgbIcon__radioB ;Or the blue view button? BEQ rgb__setView ;Yes -- set the new view CMP R0,#csEvent__close ;Is it a close panel event? BEQ rgb__closePanel ;Yes -- destroy the dialogue CMP R0,#csEvent__newRes ;Is it a resolution change? BEQ rgb__newRes ;Yes -- update the piccy then CMP R0,#slider_event ;Is it a slider event? BEQ rgb__slChange ;Yes -- do something then CMP R0,#numWrite_event ;Is it a writable event? BEQ rgb__wrChange ;Yes -- do something then CMP R0,#arrow_event ;Is it an arrow event? BEQ rgb__arChange ;Yes -- do something then STMFD R13!,{R14} ;Save a register SUB R14,R0,#rgbIcon__wCols ;Is it a WIMP colour box? CMP R14,#16 ;Check it's in range BLO rgb__wimpCol ;Yes -- handle it then LDMFD R13!,{PC}^ ;Unknown -- return to caller ; --- Change the panel view --- rgb__setView ROUT STMFD R13!,{R0-R3,R14} ;Save some registers CMP R0,#rgbIcon__radioG ;Is it the green button? MOVLT R3,#0 ;Lower -- it must be red MOVEQ R3,#1 ;Equal -- must be green MOVGT R3,#2 ;Greater -- must be blue LDR R1,rgb__mapping ;Get the current mapping CMP R3,R1 ;Is it the same? LDMEQFD R13!,{R0-R3,PC}^ ;Yes -- return now then ; --- Select the correct icon --- MOV R0,R9 ;Load the dialogue handle ADD R1,R1,R1,LSL #2 ;Multiply by icon offset (5) ADD R1,R1,#rgbIcon__radioR ;Add on to get icon number MOV R2,#0 ;Please deselect this icon BL dbox_select ;Select the right one ADD R1,R3,R3,LSL #2 ;Multiply by icon offset (5) ADD R1,R1,#rgbIcon__radioR ;Add on to get icon number MOV R2,#1 ;Please select this icon BL dbox_select ;Select the right one ; --- Update the dialogue box sliders etc. --- MOV R0,R9 ;Get the dialogue box handle MOV R1,#rgbIcon__square ;Get the colour square BL dbx_qUpdate ;Get rid of the crosshair MOV R0,R3 ;Pass mapping number BL rgb__setMapping ;Redo all the mappings BL rgb__updateSliders ;And redraw the sliders MOV R0,R9 ;Get the dialogue box handle MOV R1,#rgbIcon__square ;Get the colour square BL dbx_update ;Redraw it nicely LDMFD R13!,{R0-R3,PC}^ ;Return to caller ; --- Update the RGB colour cube view --- rgb__newRes ROUT STMFD R13!,{R0,R1,R14} ;Save some registers MOV R0,R9 ;Get the dialogue handle MOV R1,#rgbIcon__square ;Get the colour square BL dbx_qUpdate ;Get rid of the crosshair BL dbx_update ;Redraw it nicely LDMFD R13!,{R0,R1,PC}^ ;And return to caller ; --- Update colour values --- rgb__slChange ROUT STMFD R13!,{R0-R2,R4,R14} ;Save some registers ; --- Update the main dialogue's colour pot --- BL rgb__colUpdate ;Update the colour pot ; --- Now update the writable icon --- LDR R2,[R13,#8] ;Load the slider icon SUB R4,R2,#rgbIcon__slide1 ;Get the slider axis number LDR R14,rgb__mapping ;Load the mapping number SUB R1,R14,R4 ;Find the table index ADR R14,rgb__writeTbl+2 ;Point to the table LDRB R1,[R14,R1] ;Load the icon number MOV R0,R9 ;Put dialogue handle in R0 MOV R2,R3 ;Put slider value in R2 BL numWrite_set ;And put it in the icon ; --- Now work out what else to update --- CMP PC,#0 ;Clear the Z flag BL cs_immediate ;Are we doing immediate ops? LDRCC R14,[R13,#4] ;Load the subreason code CMPCC R14,#slider_sliding ;Is the slider going still? BLNE rgb__zUpdate ;No -- redraw colour square BL rgb__xyUpdate ;Now move the crosshair 90rgb__slChange LDMFD R13!,{R0-R2,R4,PC}^ ;Return to caller rgb__writeTbl DCB rgbIcon__writeR DCB rgbIcon__writeG DCB rgbIcon__writeB DCB rgbIcon__writeR DCB rgbIcon__writeG ; --- He typed something into one of our icons --- rgb__wrChange ROUT STMFD R13!,{R0-R5,R14} ;Save some registers ; --- First, find the value this writable applies to --- CMP R1,#rgbIcon__writeG ;Which writable icon is it? MOVLT R1,#0 ;Red -- remember this map MOVEQ R1,#1 ;Green -- remember this MOVGT R1,#2 ;Blue -- remember this ADR R14,rgb__red ;Point to the mappings LDR R14,[R14,R1,LSL #2] ;Translate the colour LDR R0,[R14,#0] ;Load the actual value SUBS R5,R0,R3 ;Is this our value? ; --- He's changed the value -- update slider/colour --- STRNE R3,[R14,#0] ;Save the new value away BLNE rgb__colUpdate ;Redraw the colour pot LDR R0,rgb__mapping ;Load the mapping number SUB R3,R1,R0 ;Work out the table index ADR R14,rgb__slideTbl+2 ;Point to slider icon table LDRB R1,[R14,R3] ;Load the icon number LDR R0,cs__modelDb ;Load the panel dialogue BLNE dbx_update ;Redraw the slider nicely ; --- Update the main piccy --- CMPEQ PC,#0 ;Clear the Z flag BL cs_immediate ;Are we doing immediate ops? CMPCC R2,#numWrite_change ;Is he just typing numbers? BLNE rgb__zUpdate ;No -- redraw colour square BL rgb__xyUpdate ;Now move the crosshair 90rgb__wrChange LDMFD R13!,{R0-R5,PC}^ ;Return to caller rgb__slideTbl DCB rgbIcon__slide2 DCB rgbIcon__slide1 DCB rgbIcon__slide3 DCB rgbIcon__slide2 DCB rgbIcon__slide1 rgb__arChange ROUT STMFD R13!,{R0-R4,R14} ;Save some registers MOV R4,R2 ;Look after the bump ; --- First, find the value this arrow applies to --- CMP R1,#rgbIcon__upG ;Which writable icon is it? CMPGT R1,#rgbIcon__downG ;There's two for green MOVLT R3,#0 ;Red -- remember this map MOVEQ R3,#1 ;Green -- remember this MOVGT R3,#2 ;Blue -- remember this ; --- Now bump the required writable icon --- ADR R14,rgb__writeTbl ;Point to the icon table LDRB R1,[R14,R3] ;Load the correct icon MOV R0,R9 ;Pass dialogue in R0 BL numWrite_bump ;Apply the bump value ; --- Now perform the update operation --- CMPEQ PC,#0 ;Clear the Z flag BL cs_immediate ;Are we doing immediates? TEQCS R4,#0 ;And is the bump sensible? BEQ %90rgb__arChange ;Immediate/end ==> return MOV R3,R2 ;Get value in R3 nicely MOVCS R2,#1 ;Update always if immediate MOVCC R2,#0 ;Default is no update if not TEQ R4,#0 ;And is the bump sensible? MOVEQ R2,#1 ;No -- then force update BL rgb__wrChange ;Handle writable update then 90rgb__arChange LDMFD R13!,{R0-R4,PC}^ ;And return to caller LTORG ; --- Close the panel to open a new one --- rgb__closePanel ROUT STMFD R13!,{R0,R14} ;Save some registers MOV R0,R9 ;Get the dialogue handle BL dbox_destroy ;Kill off the dialogue LDMFD R13!,{R0,PC}^ ;And return to caller ; --- Handle a click on one of the WIMP colours --- ; ; The WIMP colour number resides in R14 at the moment :-/ rgb__wimpCol ROUT STMFD R13!,{R0,R1} ;Save some registers SUB R13,R13,#80 ;Make space for palette block MOV R1,R13 ;Point to my block SWI Wimp_ReadPalette ;Read the WIMP palette LDR R1,[R13,R14,LSL #2] ;Load the one we want ADD R13,R13,#80 ;Don't need this now ; --- Under RISC OS <3.50, bodge palette entry --- ; ; Because of Acorn stupidity, the ReadPalette values have ; blank lower nibbles. According to Acorn, I must copy the ; top nibbles into the bottom ones for ColourTrans to be ; happy. I assume that this has been sorted out on 3.50 and ; later. BL rov_version ;Get the RISC OS version CMP R0,#340 ;It's almost 350 :-) LDRLO R14,=&F0F0F000 ;A nibble mask ANDLO R1,R1,R14 ;Clear bottom nibbles ORRLO R1,R1,R1,LSR #4 ;And duplicate top in bottom STR R1,cs__colour+col_rgb ;Save this new colour BL rgb__setValues ;And redo everything nicely LDMFD R13!,{R0,R1,PC}^ ;And return to caller LTORG ; --- rgb__setValues --- ; ; On entry: R10 == address of colour selector instance data ; ; On exit: -- ; ; Use: Updates all the values in the dialogue box from the colour ; word in the workspace (which is assumed to have changed). ; The colour mapping is assumed to still be valid, though. rgb__setValues ROUT STMFD R13!,{R0-R2,R14} ;Save some registers ; --- Unpack the value from the colour RGB word --- BL rgb__unpack ;Get the percentages out ; --- Do the writable icons --- LDR R0,cs__modelDb ;Get the dialogue handle MOV R1,#rgbIcon__writeR ;Get the red writable icon LDR R2,rgb__red ;Find the red value LDR R2,[R2,#0] ;Load the red value BL numWrite_set ;Set it in the icon MOV R1,#rgbIcon__writeG ;Get the green writable icon LDR R2,rgb__green ;Find the green value LDR R2,[R2,#0] ;Load the green value BL numWrite_set ;Set it in the icon MOV R1,#rgbIcon__writeB ;Get the blue writable icon LDR R2,rgb__blue ;Find the blue value LDR R2,[R2,#0] ;Load the blue value BL numWrite_set ;Set it in the icon ; --- Now do the other controls --- BL rgb__updateSliders ;Do the slider update BL cs_colChange ;Redraw main colour pot BL rgb__zUpdate ;Force a recache of z BL rgb__xyUpdate ;And a recache of x and y LDMFD R13!,{R0-R2,PC}^ ;And return to caller LTORG ; --- rgb__updateSliders --- ; ; On entry: R10 == address of colour selector instance data ; ; On exit: -- ; ; Use: Redraws all the sliders. Because the slider code is so ; amazingly intelligent, if the values haven't changed, the ; picture you see won't change either. rgb__updateSliders ROUT STMFD R13!,{R0,R1,R14} ;Save some registers LDR R0,cs__modelDb ;Get the dialogue handle MOV R1,#rgbIcon__slide1 ;Get slider 1's number BL dbx_update ;Redraw it quickly MOV R1,#rgbIcon__slide2 ;Get slider 2's number BL dbx_update ;Redraw it quickly MOV R1,#rgbIcon__slide3 ;Get slider 3's number BL dbx_update ;Redraw it quickly LDMFD R13!,{R0,R1,PC}^ ;And return to caller LTORG ; --- rgb__setMapping --- ; ; On entry: R0 == rotation number (i.e. which colour is on z azis) ; ; On exit: -- ; ; Use: Sets up the workspace so that the dialogue box displays the ; correct mapping. rgb__setMapping ROUT STMFD R13!,{R0-R3,R14} ;Save some registers ; --- Reset the mapping number and table --- STR R0,rgb__mapping ;Save the mapping number ADR R1,rgb__mappingTbl ;Point to the table ADD R1,R1,R0 ;Index it nicely LDRB R14,[R1],#1 ;Load the blue offset ADD R14,R10,R14 ;Add it to workspace ptr STR R14,rgb__blue ;And store nicely MOV R2,#8 ;The blue slider colour STR R2,[R14,#4] ;Save it in the table LDRB R14,[R1],#1 ;Load the green offset ADD R14,R10,R14 ;Add it to workspace ptr STR R14,rgb__green ;And store nicely MOV R2,#10 ;The green slider colour STR R2,[R14,#4] ;Save it in the table LDRB R14,[R1],#1 ;Load the red offset ADD R14,R10,R14 ;Add it to workspace ptr STR R14,rgb__red ;And store nicely MOV R2,#11 ;The red slider colour STR R2,[R14,#4] ;Save it in the table BL rgb__unpack ;Unpack colour def now ; --- Set up the cached values for the diagram --- LDR R14,rgb__sl1Val ;Load the x value STR R14,rgb__xPos ;Save it in the cache LDR R14,rgb__sl2Val ;Load the y value STR R14,rgb__yPos ;Save it in the cache LDR R14,rgb__sl3Val ;Load the z value STR R14,rgb__zPos ;Save it in the cache LDMFD R13!,{R0-R3,PC}^ ;Return to caller LTORG ; --- The mapping table --- ; ; The table is done twice, to give it a `wraparound' effect. rgb__mappingTbl DCB :INDEX: rgb__sl1Val DCB :INDEX: rgb__sl2Val DCB :INDEX: rgb__sl3Val DCB :INDEX: rgb__sl1Val DCB :INDEX: rgb__sl2Val ; --- rgb__unpack --- ; ; On entry: R10 == address of colour selector instance data ; ; On exit: -- ; ; Use: Unpacks the colour definition in the cs data into the ; slider values. rgb__unpack ROUT STMFD R13!,{R0-R2,R14} ;Save some workspace LDR R2,cs__colour+col_rgb ;Get the colour nicely ; --- Set up the blue slider --- MOV R0,R2,LSR #24 ;Get the blue colour value BL rgb__colToPerC ;Convert it to a percentage LDR R14,rgb__blue ;Load the blue entry address STR R0,[R14] ;Save the blue value in it ; --- Now set up the green one --- MOV R0,R2,LSR #16 ;Get the green colour value BL rgb__colToPerC ;Convert it to a percentage LDR R14,rgb__green ;Load the green entry address STR R0,[R14] ;Save the green value in it ; --- Now set up the red one --- MOV R0,R2,LSR #8 ;Get the red colour value BL rgb__colToPerC ;Convert it to a percentage LDR R14,rgb__red ;Load the red entry address STR R0,[R14] ;Save the red value in it LDMFD R13!,{R0-R2,PC}^ ;And return to caller LTORG ; --- rgb__colToPerC --- ; ; On entry: R0 == colour to convert, from 0 to 255 ; ; On exit: R0 == colour as a percentage ; ; Use: Converts a colour to a percentage. ; ; [Generated by Straylight divc] ; Modified by MDW to (a) be unsigned, and (b) round to nearest. rgb__colToPerC ROUT STMFD R13!,{R1,R14} ;Save some registers AND R0,R0,#&FF ;Mask off any other bits ADD R0,R0,R0,LSL #2 ;Multiply by 5 (x5) ADD R0,R0,R0,LSL #2 ;And by 5 again (x25) MOV R0,R0,LSL #2 ;And now by 4 (x100) MOV R1,R0 ;Keep copy of dividend ADD R0,R0,#127 ;Make it round to nearest ADD R0,R0,R0,LSR #8 ;R0 = R0 x 256/255 ADD R0,R0,R0,LSR #16 ;... MOV R0,R0,LSR #8 ;Div by 256 -- R0 = R0 / 255 RSB R14,R0,R0,LSL #8 ;Multiply by 255 SUB R1,R1,R14 ;Find the difference SUBS R1,R1,#255 ;This is the remainder ADDGE R0,R0,#1 ;If we overshot, bump quot ADDLT R1,R1,#255 ;And chop off remainder LDMFD R13!,{R1,PC}^ ;Return to caller LTORG ; --- rgb__perCToCol --- ; ; On entry: R0 == colour percentage to convert ; ; On exit: R0 == colour value, from 0-255 ; ; Use: Converts a percentage to a colour. rgb__perCToCol ROUT STMFD R13!,{R1,R14} ;Save some registers RSB R0,R0,R0,LSL #8 ;Multiply it by 255 ADD R0,R0,#50 ;Add 50 to round to nearest BL div10 ;Divide by 10 BL div10 ;And again (by 100) LDMFD R13!,{R1,PC}^ ;And return to caller LTORG ; --- rgb__colUpdate --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Updates the main dialogue's colour pot. rgb__colUpdate ROUT STMFD R13!,{R0,R2,R14} ;Save some registers MOV R2,#0 ;Clear prospective colour LDR R0,rgb__blue ;Get the blue colour address LDR R0,[R0,#0] ;Load the blue percentage BL rgb__perCToCol ;Convert it to a real colour ORR R2,R2,R0,LSL #24 ;Move into R2 nicely LDR R0,rgb__green ;Get the green colour address LDR R0,[R0,#0] ;Load the green percentage BL rgb__perCToCol ;Convert it to a real colour ORR R2,R2,R0,LSL #16 ;Move into R2 nicely LDR R0,rgb__red ;Get the red colour address LDR R0,[R0,#0] ;Load the red percentage BL rgb__perCToCol ;Convert it to a real colour ORR R2,R2,R0,LSL #8 ;Move into R2 nicely STR R2,cs__colour+col_rgb ;Save this as the new colour LDMFD R13!,{R0,R2,R14} ;Restore registers B cs_colChange ;Update the main box's colour LTORG ; --- rgb__zUpdate --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Updates everything following a change to the current z ; value. It doesn't change the writable icon, but it does ; most other things. rgb__zUpdate ROUT STMFD R13!,{R0-R2,R14} ;Save some registers ; --- Make sure that the z coordinate changed --- LDR R2,rgb__sl3Val ;Load current z slider pos LDR R0,rgb__zPos ;Load the cached position CMP R0,R2 ;Do they match? LDMEQFD R13!,{R0-R2,PC}^ ;Yes -- nothing doing then ; --- Remove crosshairs -- it looks nicer --- LDR R0,cs__modelDb ;Load the model dialogue MOV R1,#rgbIcon__square ;Get the colour square BL dbx_qUpdate ;Get rid of the crosshair ; --- Now recache the x and y coords to prevent flicker --- STR R2,rgb__zPos ;Update the cache value LDR R14,rgb__sl1Val ;Load the current x value STR R14,rgb__xPos ;Save it away LDR R14,rgb__sl2Val ;Load the current y value STR R14,rgb__yPos ;Save it away ; --- Redraw the main square --- BL dbx_update ;Force a redraw of it LDMFD R13!,{R0-R2,PC}^ ;And return to caller LTORG ; --- rgb__xyUpdate --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Updates things following a change to either the x or y ; value. rgb__xyUpdate ROUT STMFD R13!,{R0-R3,R14} ;Save some registers LDR R0,rgb__xPos ;Load cached x position LDR R1,rgb__yPos ;Load cached y position LDR R2,rgb__sl1Val ;And the current x pos LDR R3,rgb__sl2Val ;And the current y pos CMP R0,R2 ;Is the cached x right? CMPEQ R1,R3 ;And is the cached y right? LDMEQFD R13!,{R0-R3,PC}^ ;Yes -- return then LDR R0,cs__modelDb ;Load the dialogue box handle MOV R1,#rgbIcon__square ;Load the square icon BL dbx_qUpdate ;Quickly redraw it STR R2,rgb__xPos ;Recache the x position STR R3,rgb__yPos ;Recache the y position BL dbx_qUpdate ;Quickly redraw it LDMFD R13!,{R0-R3,PC}^ ;Return to caller LTORG ;----- Plotting the colour square ------------------------------------------- ; --- rgb_plotSquare --- ; ; On entry: R0 == left hand side of colour square to plot ; R1 == bottom edge of colour square to plot ; R2 == which rotation we're plotting ; R3 == x step to plot in ; R4 == y step to plot in ; R5 == z-coordinate value (in 16.16 form) ; R6 == pointer to graphics window block ; ; On exit: -- ; ; Use: Plots a cross-section through the RGB colour cube. EXPORT rgb_plotSquare rgb_plotSquare ROUT STMFD R13!,{R0-R12,R14} ;Save a job-lot of registers ; --- Work out the minimum coordinates --- LDMIA R6,{R8,R9,R11,R12} ;Load the coordinates out SUB R7,R12,R1 ;Translate max y to relative SUB R12,R9,R1 ;Translate min y too SUB R10,R8,R0 ;Translate min x too SUB R11,R11,R0 ;Translate max x ; --- See if we can do really clever things --- STMFD R13!,{R0,R11} ;Save our R11 value LDR R11,[R13,#52] ;Load the system R11 value BL screen_getInfo ;Load the screen information MOV R8,R0 ;Look after this address LDMFD R13!,{R0,R11} ;Reload our local value LDR R14,[R8,#screen_bpp] ;Load current bits/pixel CMP R14,#16 ;Is this a 2byte/pixel mode? BEQ rgb__plot32k ;Yes -- branch to special bit CMP R14,#32 ;Is this a 4byte/pixel mode? BEQ rgb__plot16m ;Yes -- branch to special bit ; --- Work out rectangle edges --- CMP R10,#0 ;Is min x too small? MOVLT R10,#0 ;Yes -- raise it to 0 CMP R12,#0 ;Is min y too small? MOVLT R12,#0 ;Yes --- raise that too CMP R11,#255 ;Is the max x too large? MOVGT R11,#255 ;Yes -- reduce it then CMP R7,#255 ;Is the max y too large? MOVGT R7,#255 ;Yes -- reduce it then SUB R8,R3,#1 ;Turn the x step to bitmask SUB R9,R4,#1 ;And the same for y step BIC R10,R10,R8 ;Round min x down to step BIC R12,R12,R9 ;And round min y down too BIC R11,R11,R8 ;Round max x down too BIC R7,R7,R9 ;And round down max y STMFD R13!,{R7,R10} ;Save rel. min x and max y ADD R10,R10,R0 ;Now make min x absolute ADD R12,R12,R1 ;And make min y absolute ADD R11,R11,R0 ;And make max x absolute ADD R7,R7,R1 ;And make max y absolute ; --- Now work out the z-value --- RSB R5,R5,R5,LSL #8 ;Multiply value by 255 ADD R5,R5,#&8000 ;Make sure we round nicely MOV R5,R5,LSR #16 ;And make it 0-255 ; --- Work out the exclusive rectangle sizes --- STMFD R13!,{R11} ;Save our R11 value LDR R11,[R13,#56] ;Load the system R11 value BL screen_getInfo ;Load the screen information LDMFD R13!,{R11} ;Reload our local value LDMIA R0,{R8,R9} ;Load the eigen factors out MOV R14,#1 ;This will be shifted around SUB R8,R3,R14,LSL R8 ;Subtract x pixel from x step SUB R9,R4,R14,LSL R9 ;Subtract y pixel from y step ; --- Work out all the shift values --- CMP R2,#0 ;Is this the red rotation? MOVEQ R0,#24 ;Yes -- then x is blue MOVEQ R1,#16 ;And y is green MOVEQ R5,R5,LSL #8 ;And z is red CMP R2,#1 ;Is this the green rotation? MOVEQ R0,#8 ;Yes -- then x is red MOVEQ R1,#24 ;And y is blue MOVEQ R5,R5,LSL #16 ;And z is green CMP R2,#2 ;Is this the blue rotation? MOVEQ R0,#16 ;Yes -- then x is green MOVEQ R1,#8 ;And y is red MOVEQ R5,R5,LSL #24 ;And z is blue ; --- Set up the initial palette word --- LDMFD R13!,{R14} ;Load maximum y palette val ORR R5,R5,R14,LSL R1 ;Fit that into the palette LDMFD R13!,{R2} ;Load minimum x palette val ; --- Now for the main plotting loop --- 00 MOV R6,R10 ;Start on the left hand side MOV R14,#255 ;Clear out nasty x palette BIC R5,R5,R14,LSL R0 ;Clear out the right byte ORR R5,R5,R2,LSL R0 ;And set up the min value ; --- Plot the rectangle nicely --- 10 STMFD R13!,{R0-R4} ;Save some registers for this ; --- Nothing for it but to use ColourTrans --- MOV R0,R5 ;Get the palette entry MOV R3,#&100 ;Please try to dither it MOV R4,#0 ;And have normal GCOL action SWI XColourTrans_SetGCOL ;Try to set the colour up MOVVS R3,#0 ;Try again without dithering MOVVS R0,R5 ;Set the palette word again SWIVS ColourTrans_SetGCOL ;Set the colour the old way 15 MOV R0,#4 ;Move cursor absolute MOV R1,R6 ;Get the current x coordinate MOV R2,R7 ;And the current y coordinate SWI OS_Plot ;Move the cursor there MOV R0,#97 ;Rectangle fill relative MOV R1,R8 ;Rectangle width thingy MOV R2,R9 ;Rectangle height thingy SWI OS_Plot ;Plot the rectangle LDMFD R13!,{R0-R4} ;Restore a load of registers ; --- Now move on to the next square --- ADD R6,R6,R3 ;Add on the x increment CMP R6,R11 ;Have we gone too far? ADDLE R5,R5,R3,LSL R0 ;No -- add on the palette val BLE %10rgb_plotSquare ;And go round again SUB R7,R7,R4 ;Subtract the y increment CMP R7,R12 ;Have we gone too far? SUBGE R5,R5,R4,LSL R1 ;No -- subtract palette val BGE %00rgb_plotSquare ;And do the next row nicely LDMFD R13!,{R0-R12,PC}^ ;Return to caller ; --- Fast colour setting routines --- 20 MOV R1,R5,LSR #8 ;Get hardware colour value MOV R0,#0 ;Set the colour SWI OS_SetColour ;Set the colour really B %15rgb_plotSquare ;And return to main loop 25 AND R0,R5,#&F800 ;Get the red bits out MOV R1,R0,LSR #11 ;Shift them down AND R0,R5,#&F80000 ;Get the green bits ORR R1,R1,R0,LSR #14 ;Move them in nicely AND R0,R5,#&F8000000 ;Get the blue bits too ORR R1,R1,R0,LSR #17 ;Move them in too MOV R0,#0 ;Set a raw colour SWI OS_SetColour ;Set the colour nicely B %15rgb_plotSquare ;And return to main loop 30 MOV R14,#3 ;Mask bits off quickly AND R0,R14,R5,LSR #12 ;Get the red bits AND R1,R14,R5,LSR #20 ;Get the green bits AND R2,R14,R5,LSR #28 ;And the blue bits ADD R1,R1,R1,LSL #2 ;Multiply green by 5 ADD R2,R2,R0,LSL #1 ;Mult red by 2 and add in ADD R2,R2,R1 ;And add in weighted green MOV R1,R2,LSR #3 ;Get weighted average AND R0,R5,#&00C00000 ;Get top two green bits ORR R1,R1,R0,LSR #17 ;Shift into position TST R5,#&00004000 ;Get red bit two ORRNE R1,R1,#&4 ;If set, set in colour TST R5,#&40000000 ;Get blue bit two ORRNE R1,R1,#&8 ;If set, set in colour TST R5,#&00008000 ;Get red bit three ORRNE R1,R1,#&10 ;If set, set in colour TST R5,#&80000000 ;Get blue bit three ORRNE R1,R1,#&80 ;If set, set in colour MOV R0,#0 ;Set raw colour SWI OS_SetColour ;Do the colour setting B %15rgb_plotSquare ;And return to main loop LTORG ; --- rgb__plot32k --- ; ; On entry: R0 == left side of square to plot ; R1 == bottom of square to plot ; R2 == rotation number ; R3 == x step for rectangles ; R4 == y step for rectangles ; R5 == current z-value (in 16.16) ; R6 == pointer to graphics window block ; R7 == unlimited relative max y position to plot ; R8 == pointer to screen info block ; R10 == unlimited relative min x position to plot ; R11 == unlimited relative max x position to plot ; R12 == unlimited relative min y position to plot ; On stack: saved {R0-R12,R14} ; ; On exit: -- ; ; Use: Displays an RGB square on the screen at a given location, ; in a 16bpp mode, using direct screen access (TM). rgb__plot32k ROUT ; --- Prologue: Limit the relative box positions --- ADD R8,R8,#screen_dx ;Find the pixel positions LDMIA R8,{R8,R9} ;Load them into registers CMP R10,#0 ;Is min x too small? MOVLT R10,#0 ;Yes -- raise it to 0 CMP R12,#0 ;Is min y too small? MOVLT R12,#0 ;Yes --- raise that too CMP R11,#256 ;Is the max x too large? MOVGT R11,#256 ;Yes -- reduce it then CMP R7,#256 ;Is the max y too large? MOVGT R7,#256 ;Yes -- reduce it then SUB R11,R11,R8 ;Make this inclusive SUB R7,R7,R9 ;Make this inclusive too ; --- Act 1: Find addresses of things on the screen --- ADD R9,R0,R10 ;Work out left hand side ADD R8,R1,R7 ;Work out top of area SUB R10,R11,R10 ;Work out width of area SUB R7,R7,R12 ;And the height too SUB R12,R9,R0 ;Work out left offset again SUB R11,R8,R1 ;And the top offset too SUB R13,R13,#20 ;Space for our vdu vars ADR R0,rgb__vduVars ;Point to the var numbers MOV R1,R13 ;Point to our output block SWI OS_ReadVduVariables ;Get the values nicely ; --- Interlude: Set up rectangle sizes --- CMP R3,#8 ;Make sure rectangles are >8 MOVCC R3,#8 ;If not, make them bigger MOVCC R4,#8 ;(Width and height the same) MOV R14,R3,LSR #3 ;Work out colour increment ; --- Reprise: Convert measurements to pixels --- LDMIA R13!,{R0,R1} ;Load the x and y eig things MOV R3,R3,LSR R0 ;Convert pixel counters MOV R4,R4,LSR R1 ;Convert other pixel counter MOV R9,R9,LSR R0 ;Convert left hand side MOV R10,R10,LSR R0 ;Convert width of area MOV R7,R7,LSR R1 ;Convert area height MOV R8,R8,LSR R1 ;And the top position ; --- Intermission: Pack up pixel counters --- ; ; We pack all this into a word containing the following: ; ; bits 31-24 == x counter reset value ; bits 23-20 == y counter initial value ; bits 19-16 == x counter initial value ; bits 15- 8 == y counter reset value ; bits 7- 0 == colour step value ; ; Can anyone say `Z80 programming techniques'? MOV R12,R12,LSR R0 ;Get left offset in pixels SUB R6,R3,#1 ;Get the h pixel count -1 AND R0,R12,R6 ;Get the remainder thing SUB R0,R3,R0 ;And get the correct offset ORR R3,R4,R3,LSL #16 ;Pack x and y counters ORR R3,R14,R3,LSL #8 ;And move in the colour inc RSB R14,R11,#256 ;Get offset from top MOV R11,R11,LSR R1 ;Turn offset into pixels MOV R1,R14,LSR R1 ;Get top offset in pixels SUB R1,R1,#1 ;Subtract one for niceness SUB R6,R4,#1 ;Get the v pixel count -1 AND R1,R1,R6 ;Get the remainder thing SUB R1,R4,R1 ;And get the correct offset ORR R0,R0,R1,LSL #4 ;Pack into 1 byte ORR R3,R3,R0,LSL #16 ;Put in initial values too LDMIA R13!,{R0,R1,R6} ;Load other vdu vars SUB R14,R1,R8 ;Shift origin to top left MLA R0,R14,R6,R0 ;Work out address of row ADD R9,R0,R9,LSL #1 ;Work out left address ADD R8,R9,R10,LSL #1 ;Work out right hand side too ; --- Act 2: Set up colour information --- AND R14,R3,#&FF ;Get the colour step value BIC R10,R3,#&FF ;Move packed init values away RSB R5,R5,R5,LSL #8 ;Multiply z value by 255 MOV R5,R5,LSR #19 ;And make it 0-31 AND R3,R10,#&FF000000 ;Get the x pixel count reinit SUB R3,R3,#&01000000 ;Turn it into a bitmask BIC R3,R12,R3,LSR #24 ;Round colour down nicely LDR R12,[R13,#-20] ;Get the xeig factor MOV R3,R3,LSL R12 ;Shift colour up to OS units MOV R3,R3,LSR #3 ;Get the x colour in 0-31 AND R4,R10,#&0000FF00 ;Get the y pixel count reinit SUB R4,R4,#&00000100 ;Turn it into a bitmask BIC R4,R11,R4,LSR #8 ;Round colour down nicely LDR R11,[R13,#-16] ;Get the yeig factor MOV R4,R4,LSL R11 ;Shift colour up to OS units MOV R4,R4,LSR #3 ;And the y one too please MOV R12,#&1F ;This is a useful value CMP R2,#0 ;Is this the red rotation? MOVEQ R0,R5,LSL #16 ;Build the colour up... ORREQ R0,R0,R4,LSL #21 ;Still doing that... ORREQ R0,R0,R3,LSL #26 ;Almost finished now... MOVEQ R1,R3,LSL #26 ;And the x-init value MOVEQ R3,R14,LSL #21 ;Get the y increment right MOVEQ R4,R14,LSL #26 ;And the x increment MOVEQ R5,R12,LSL #26 ;Get the x-clear mask CMP R2,#1 ;Is this the green rotation? MOVEQ R0,R3,LSL #16 ;Build the colour up... ORREQ R0,R0,R5,LSL #21 ;Still doing that... ORREQ R0,R0,R4,LSL #26 ;Almost finished now... MOVEQ R1,R3,LSL #16 ;And the x-init value MOVEQ R3,R14,LSL #26 ;Get the y increment right MOVEQ R4,R14,LSL #16 ;And the x increment MOVEQ R5,R12,LSL #16 ;Get the x-clear mask CMP R2,#2 ;Is this the blue rotation? MOVEQ R0,R4,LSL #16 ;Build the colour up... ORREQ R0,R0,R3,LSL #21 ;Still doing that... ORREQ R0,R0,R5,LSL #26 ;Almost finished now... MOVEQ R1,R3,LSL #21 ;Get the x-init value MOVEQ R3,R14,LSL #16 ;Get the y increment right MOVEQ R4,R14,LSL #21 ;And the x increment MOVEQ R5,R12,LSL #21 ;Get the x-clear mask ; --- Act 3. Initialise the pixel counts --- MOV R14,#&F ;For reading nibbles AND R12,R14,R10,LSR #16 ;Get the initial x value AND R2,R14,R10,LSR #20 ;Get the initial y value too ORR R2,R10,R2 ;Put that into the count reg SWI OS_EnterOS ;Avoid problems with PhysMem ; --- Act 4. Plot the bloody thing --- 10rgb__plot32k MOV R10,R9 ;Get the current address MOV R11,#0 ;Clear the buffer value STMFD R13!,{R12} ;Save the x count value ; --- Start plotting this row --- TST R10,#2 ;Is this address aligned? BEQ %20rgb__plot32k ;Yes -- start at main loop LDR R14,[R10,#-2] ;No -- load word from here MOV R14,R14,LSL #16 ;Shift all the way up ORR R14,R0,R14,LSR #16 ;Build the replacement word STR R14,[R10,#-2] ;And store in frame buffer B %25rgb__plot32k ;Jump to end of loop ; --- Main row plotting loop (time critical :-) ) --- 20rgb__plot32k ORR R11,R0,R11,LSR #16 ;Add colour into buffer TST R10,#2 ;Is this an odd address? STRNE R11,[R10,#-2] ;Yes -- done both halfwords 25rgb__plot32k ADD R10,R10,#2 ;Move on to next pixel CMP R10,R8 ;Have we finished yet? BHI %30rgb__plot32k ;No -- do the rest then SUBS R12,R12,#1 ;Decrement pixel counter ADDEQ R0,R0,R4 ;If cleared, add on colour MOVEQ R12,R2,LSR #24 ;And reinitialise counter B %20rgb__plot32k ;Go round for more ; --- We've finished; do we have a halfword left over? --- 30rgb__plot32k TST R10,#2 ;Is the address odd? LDRNE R14,[R10,#-2] ;Yes -- read the old word MOVNE R11,R11,LSR #16 ;Get buffer value in low hw MOVNE R14,R14,LSR #16 ;Get screen value in low hw ORRNE R14,R11,R14,LSL #16 ;Build correct word to write STRNE R14,[R10,#-2] ;Store this word away ; --- Now move on to the next row --- LDMFD R13!,{R12} ;Unstack initial x counter ADD R9,R9,R6 ;Move start address down 1 ADD R8,R8,R6 ;Move end address down 1 BIC R0,R0,R5 ;Clear the x colour section ORR R0,R0,R1 ;Reintialise the x colour SUB R2,R2,#1 ;Decrement y counter TST R2,#&FF ;Is it now zero? BICEQ R2,R2,#&00FF0000 ;Clear unused byte in word ORREQ R2,R2,R2,LSR #8 ;Yes -- reinitialise SUBEQ R0,R0,R3 ;And increment the y colour SUBS R7,R7,#1 ;Decrement scan line counter BCS %10rgb__plot32k ;And go back up again TEQP PC,#0 ;Return to user mode MOV R0,R0 ;Keep ARM ecstatically happy LDMFD R13!,{R0-R12,PC}^ ;Return to caller rgb__vduVars DCD 4,5 ;X and Y eigen factors DCD 149 ;Start of display memory DCD 12 ;How high is the screen DCD 6 ;Width of scan line in pixels DCD -1 LTORG ; --- rgb__plot16m --- ; ; On entry: R0 == left side of square to plot ; R1 == bottom of square to plot ; R2 == rotation number ; R3 == x step for rectangles ; R4 == y step for rectangles ; R5 == current z-value (in 16.16) ; R6 == pointer to graphics window block ; R7 == unlimited relative max y position to plot ; R8 == pointer to screen info block ; R10 == unlimited relative min x position to plot ; R11 == unlimited relative max x position to plot ; R12 == unlimited relative min y position to plot ; On stack: saved {R0-R12,R14} ; ; On exit: -- ; ; Use: Displays an RGB square on the screen at a given location, ; in a 32bpp mode, using direct screen access (TM). rgb__plot16m ROUT ; --- Prologue: Limit the relative box positions --- ADD R8,R8,#screen_dx ;Find the pixel positions LDMIA R8,{R8,R9} ;Load them into registers CMP R10,#0 ;Is min x too small? MOVLT R10,#0 ;Yes -- raise it to 0 CMP R12,#0 ;Is min y too small? MOVLT R12,#0 ;Yes --- raise that too CMP R11,#256 ;Is the max x too large? MOVGT R11,#256 ;Yes -- reduce it then CMP R7,#256 ;Is the max y too large? MOVGT R7,#256 ;Yes -- reduce it then SUB R11,R11,R8 ;Make this inclusive SUB R7,R7,R9 ;Make this inclusive too ; --- Act 1: Find addresses of things on the screen --- ADD R9,R0,R10 ;Work out left hand side ADD R8,R1,R7 ;Work out top of area SUB R10,R11,R10 ;Work out width of area SUB R7,R7,R12 ;And the height too SUB R12,R9,R0 ;Work out left offset again SUB R11,R8,R1 ;And the top offset too SUB R13,R13,#20 ;Space for our vdu vars ADR R0,rgb__vduVars ;Point to the var numbers MOV R1,R13 ;Point to our output block SWI OS_ReadVduVariables ;Get the values nicely ; --- Reprise: Convert measurements to pixels --- LDMIA R13!,{R0,R1} ;Load the x and y eig things MOV R3,R3,LSR R0 ;Convert pixel counters MOV R4,R4,LSR R1 ;Convert other pixel counter MOV R9,R9,LSR R0 ;Convert left hand side MOV R10,R10,LSR R0 ;Convert width of area MOV R7,R7,LSR R1 ;Convert area height MOV R8,R8,LSR R1 ;And the top position ; --- Intermission: Pack up pixel counters --- ; ; We pack all this into a word containing the following: ; ; bits 31-24 == x counter reset value ; bits 23-20 == y counter initial value ; bits 19-16 == x counter initial value ; bits 15- 8 == y counter reset value ; bits 7- 0 == colour step value ; ; Can anyone say `Z80 programming techniques'? MOV R12,R12,LSR R0 ;Get left offset in pixels SUB R6,R3,#1 ;Get the h pixel count -1 AND R0,R12,R6 ;Get the remainder thing SUB R0,R3,R0 ;And get the correct offset ORR R3,R4,R3,LSL #16 ;Pack x and y counters MOV R3,R3,LSL #8 ;Move that up one byte RSB R14,R11,#256 ;Get offset from top MOV R11,R11,LSR R1 ;Turn offset into pixels MOV R1,R14,LSR R1 ;Get top offset in pixels SUB R1,R1,#1 ;Subtract one for niceness SUB R6,R4,#1 ;Get the v pixel count -1 AND R1,R1,R6 ;Get the remainder thing SUB R1,R4,R1 ;And get the correct offset ORR R0,R0,R1,LSL #4 ;Pack into 1 byte ORR R3,R3,R0,LSL #16 ;Put in initial values too LDMIA R13!,{R0,R1,R6} ;Load other vdu vars SUB R14,R1,R8 ;Shift origin to top left MLA R0,R14,R6,R0 ;Work out address of row ADD R9,R0,R9,LSL #2 ;Work out left address ADD R8,R9,R10,LSL #2 ;Work out right hand side too ; --- Act 2: Set up colour information --- BIC R10,R3,#&FF ;Move packed init values away RSB R5,R5,R5,LSL #8 ;Multiply z value by 255 MOV R5,R5,LSR #16 ;And make it 0-255 AND R3,R10,#&FF000000 ;Get the x pixel count reinit SUB R3,R3,#&01000000 ;Turn it into a bitmask BIC R3,R12,R3,LSR #24 ;Round colour down nicely LDR R12,[R13,#-20] ;Get the xeig factor MOV R3,R3,LSL R12 ;Shift colour up to OS units AND R14,R10,#&FF000000 ;Get the x reinit value MOV R14,R14,LSR #24 ;Bring it down to earth MOV R14,R14,LSL R12 ;And turn into OS units AND R4,R10,#&0000FF00 ;Get the y pixel count reinit SUB R4,R4,#&00000100 ;Turn it into a bitmask BIC R4,R11,R4,LSR #8 ;Round colour down nicely LDR R12,[R13,#-16] ;Get the yeig factor MOV R4,R4,LSL R12 ;Shift colour up to OS units AND R11,R10,#&0000FF00 ;Get the y reinit value MOV R11,R11,LSR #8 ;Bring it down to earth MOV R11,R11,LSL R12 ;And turn into OS units MOV R12,#&FF ;This is a useful value CMP R2,#0 ;Is this the red rotation? MOVEQ R0,R5,LSL #0 ;Build the colour up... ORREQ R0,R0,R4,LSL #8 ;Still doing that... ORREQ R0,R0,R3,LSL #16 ;Almost finished now... MOVEQ R1,R3,LSL #16 ;And the x-init value MOVEQ R3,R11,LSL #8 ;Get the y increment right MOVEQ R4,R14,LSL #16 ;And the x increment MOVEQ R5,R12,LSL #16 ;Get the x-clear mask CMP R2,#1 ;Is this the green rotation? MOVEQ R0,R3,LSL #0 ;Build the colour up... ORREQ R0,R0,R5,LSL #8 ;Still doing that... ORREQ R0,R0,R4,LSL #16 ;Almost finished now... MOVEQ R1,R3,LSL #0 ;And the x-init value MOVEQ R3,R11,LSL #16 ;Get the y increment right MOVEQ R4,R14,LSL #0 ;And the x increment MOVEQ R5,R12,LSL #0 ;Get the x-clear mask CMP R2,#2 ;Is this the blue rotation? MOVEQ R0,R4,LSL #0 ;Build the colour up... ORREQ R0,R0,R3,LSL #8 ;Still doing that... ORREQ R0,R0,R5,LSL #16 ;Almost finished now... MOVEQ R1,R3,LSL #8 ;Get the x-init value MOVEQ R3,R11,LSL #0 ;Get the y increment right MOVEQ R4,R14,LSL #8 ;And the x increment MOVEQ R5,R12,LSL #8 ;Get the x-clear mask ; --- Act 3. Initialise the pixel counts --- MOV R14,#&F ;For reading nibbles AND R12,R14,R10,LSR #16 ;Get the initial x value AND R2,R14,R10,LSR #20 ;Get the initial y value too ORR R2,R10,R2 ;Put that into the count reg ; --- Act 4. Plot the bloody thing --- SWI OS_EnterOS ;Avoid problems with PhysMem 10rgb__plot16m MOV R10,R9 ;Get the current address MOV R11,R12 ;Initialise the x counter ; --- Main row plotting loop (time critical :-) ) --- 20rgb__plot16m STR R0,[R10],#4 ;Store this pixel 25rgb__plot16m CMP R10,R8 ;Have we finished yet? BHI %30rgb__plot16m ;No -- do the rest then SUBS R11,R11,#1 ;Decrement pixel counter ADDEQ R0,R0,R4 ;If cleared, add on colour MOVEQ R11,R2,LSR #24 ;And reinitialise counter B %20rgb__plot16m ;Go round for more ; --- We've finished; move on to next row --- 30rgb__plot16m ADD R9,R9,R6 ;Move start address down 1 ADD R8,R8,R6 ;Move end address down 1 BIC R0,R0,R5 ;Clear the x colour section ORR R0,R0,R1 ;Reintialise the x colour SUB R2,R2,#1 ;Decrement y counter TST R2,#&FF ;Is it now zero? BICEQ R2,R2,#&00FF0000 ;Clear unused byte in word ORREQ R2,R2,R2,LSR #8 ;Yes -- reinitialise SUBEQ R0,R0,R3 ;And increment the y colour SUBS R7,R7,#1 ;Decrement scan line counter BCS %10rgb__plot16m ;And go back up again TEQP PC,#0 ;Return to user mode MOV R0,R0 ;Keep ARM ecstatically happy LDMFD R13!,{R0-R12,PC}^ ;Return to caller LTORG ; --- rgb__plotHair --- ; ; On entry: R2 == x coordinate of cross ; R3 == y coordinate of cross ; ; On exit: -- ; ; Use: Plots the crosshair on an RGB colour square to mark the ; current position nicely. rgb__plotHair ROUT STMFD R13!,{R0-R3,R14} ;Save some registers MOV R0,#4 ;Move cursor absolute MOV R1,R2 ;Get the x coordinate SUB R2,R3,#256 ;Move down a little bit SWI OS_Plot ;Move the cursor there MOV R0,#2 ;Plot in logical inverse (!) MOV R1,#0 ;No x movement please MOV R2,#512 ;And plot upwards SWI OS_Plot ;Plot the vertical line MOV R0,#0 ;Move cursor relative MOV R1,#-256 ;Move back a bit MOV R2,#-256 ;Move down a bit SWI OS_Plot ;Move the cursor there MOV R0,#2 ;Plot in logical inverse (!) MOV R1,#512 ;Plot the cross beam MOV R2,#0 ;No y movement please SWI OS_Plot ;Plot the horizontal line MOV R0,#0 ;Move cursor relative MOV R1,#-256 ;Move back a bit MOV R2,#0 ;Move back to centre SWI OS_Plot ;Move the cursor there MOV R0,#146 ;Circle relative MOV R1,#16 ;Radius 16 MOV R2,#0 ;Don't screw up calculation SWI OS_Plot ;Plot the circle LDMFD R13!,{R0-R3,PC}^ ;And return to caller LTORG ;----- Custom dbx controls -------------------------------------------------- ; --- rgbSquare --- rgbSquare ROUT DCD 0,0 DCD dbxMask_redraw + dbxMask_update + dbxMask_click CMP R0,#dbxEvent_update ;Is it an update event? BEQ %10rgbSquare ;Yes -- handle it CMP R0,#dbxEvent_click ;Is it a click event? BEQ %20rgbSquare ;Yes -- handle it ; --- Deal with a redraw event --- STMFD R13!,{R0-R6,R10,R14} ;Save some registers MOV R10,R8 ;Get dbox data in R10 STMFD R13!,{R2,R3} ;Save bottom left corner ; --- Sort out the resolution --- BL cs_resolution ;Get the current resolution CMP R0,#0 ;Is it pixel-level? BLEQ screen_getInfo ;Yes -- get screen info ADDEQ R0,R0,#screen_dx ;Point to the pixel size LDMEQIA R0,{R3,R4} ;And load the values ADRNE R14,rgb__resTable ;Otherwise point at the table ADDNE R14,R14,R0 ;Find the correct entry LDRNEB R3,[R14,#0] ;Load the square size MOVNE R4,R3 ;And do it in both directions ; --- Sort out the z value too --- LDR R0,rgb__zPos ;Get the z slider value MOV R0,R0,LSL #16 ;Convert to 16.16 form ADD R0,R0,#50 ;Make it round to nearest BL div10 ;Divide it by 10 BL div10 ;And again -- div by 100 MOV R5,R0 ;This is the z coordinate ; --- Call the main plot code --- LDMFD R13!,{R0,R1} ;Load the bottom left corner LDR R2,rgb__mapping ;Get the colour mapping BL rgb_plotSquare ;Do the plotting LDMFD R13!,{R0-R6,R10,R14} ;Drop through to update code ; --- Plot the crosshair as part of update --- 10rgbSquare STMFD R13!,{R0-R5,R10,R14} ;Save some registers MOV R10,R8 ;Find my workspace address SUB R4,R4,R2 ;Get the icon width SUB R5,R5,R3 ;And the height LDR R0,rgb__xPos ;Load cached x position MUL R0,R4,R0 ;Scale it to the width ADD R0,R0,#50 ;Round to nearest on divide BL div10 ;And divide down BL div10 ;And divide down again ADD R2,R2,R0 ;Find the x cross position LDR R0,rgb__yPos ;Load cached y position MUL R0,R5,R0 ;Scale it to the height ADD R0,R0,#50 ;Round to nearest on divide BL div10 ;And divide down BL div10 ;And divide down again ADD R3,R3,R0 ;Find the y cross position BL rgb__plotHair ;Plot the crosshair nicely LDMFD R13!,{R0-R5,R10,PC}^ ;And return to caller rgb__resTable DCB 0,4,8,16 ; --- Handle click events on the square --- 20rgbSquare TST R2,#5 ;Is it a real button click? MOVEQS PC,R14 ;No -- ignore it then STMFD R13!,{R0-R5,R10,R14} ;Save some registers ; --- Start the drag operation --- MOV R0,R10 ;Get dialogue handle BL dbx_controlBBox ;Get the bonding box nicely BL dbox_window ;Get the window handle MOV R1,#7 ;User drag type SUB R13,R13,#56 ;Make a drag box on the stack STMIA R13,{R0,R1} ;Save them away nicely ADD R14,R13,#24 ;Point to parent box STMIA R14,{R2-R5} ;Save the bounding box here MOV R1,R13 ;Point to my block SWI Wimp_DragBox ;Set up the drag nicely ADD R13,R13,#56 ;Reclaim the stack space ; --- Set up the handlers nicely --- MOV R10,R8 ;Point to dbox data in R10 ADR R0,rgb__ukEvents ;Point to unknown handler MOV R1,#0 ;Don't care about R4 MOV R2,R10 ;Pass dbox data in R10 MOV R3,R12 ;Pass workspace in R12 BL win_unknownHandler ;Register the handler MOVVC R0,#2 ;Call every TV frame ADRVC R1,rgb__idles ;Point to the idle handler BLVC idle_handler ;Register that too BL rgb__idles ;Call idle handler now LDMFD R13!,{R0-R5,R10,PC}^ ;Return to caller LTORG ; --- rgb__idles --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Handles idle events during a drag in the colour square. rgb__idles ROUT STMFD R13!,{R0-R5,R10,R14} ;Save some registers LDR R0,cs__modelDb ;Get the dialogue box MOV R1,#rgbIcon__square ;Get my icon handle BL dbx_controlBBox ;Get my bounding box nicely SUB R13,R13,#20 ;Get a pointer block MOV R1,R13 ;Point at it nicely SWI Wimp_GetPointerInfo ;Find the pointer posn LDMIA R13,{R0,R1} ;Load pointer coordinates ADD R13,R13,#20 ;Recover that block ; --- Work out the new cross position --- SUB R4,R4,R2 ;Work out the icon width SUB R5,R5,R3 ;And the icon height SUB R2,R0,R2 ;Work out the x offset SUB R3,R1,R3 ;And the y offset ADD R2,R2,R2,LSL #2 ;Multiply x by 5 ADD R2,R2,R2,LSL #2 ;Multiply x by 5 (x25) MOV R2,R2,LSL #2 ;Multiply x by 4 (x100) ADD R3,R3,R3,LSL #2 ;Multiply y by 5 ADD R3,R3,R3,LSL #2 ;Multiply y by 5 (x25) MOV R3,R3,LSL #2 ;Multiply y by 4 (x100) MOV R0,R2 ;Get the x value MOV R1,R4 ;And the icon width BL div_round ;Divide to get percentage STR R0,rgb__sl1Val ;Save the x position MOV R0,R3 ;Get the y value MOV R1,R5 ;And the icon height BL div_round ;Divide to get percentage STR R0,rgb__sl2Val ;Save the y position BL rgb__xyUpdate ;Redraw crosshairs if reqd LDR R0,cs__modelDb ;Get the dialogue handle MOV R1,#rgbIcon__slide1 ;Get slider 1's number BL dbx_update ;Redraw it quickly MOV R1,#rgbIcon__slide2 ;Get slider 2's number BL dbx_update ;Redraw it quickly BL rgb__colUpdate ;Redraw the colour button ; --- Now update the correct icons --- ADRL R5,rgb__writeTbl+2 ;Point to icon number table LDR R14,rgb__mapping ;And get the current mappiing ADD R5,R5,R14 ;Find the correct entry LDRB R1,[R5,#0] ;Load the x icon LDR R2,rgb__sl1Val ;Get the new x value BL numWrite_set ;Put it in the icon LDRB R1,[R5,#-1] ;Load the y icon LDR R2,rgb__sl2Val ;Get the new y value BL numWrite_set ;Put it in the icon LDMFD R13!,{R0-R5,R10,PC}^ ;And return to caller LTORG ; --- rgb__ukEvents --- ; ; On entry: R0 == event code ; ; On exit: CS if handled ; ; Use: Handles unknown events during a drag in the RGB colour ; square. rgb__ukEvents ROUT CMP R0,#7 ;Is it a drag over event? MOVNES PC,R14 ;No -- then return to caller STMFD R13!,{R0-R3,R14} ;Save some registers BL rgb__idles ;Get one last drag position ADR R0,rgb__ukEvents ;Point to unknown handler MOV R1,#0 ;Don't care about R4 MOV R2,R10 ;Pass dbox data in R10 MOV R3,R12 ;Pass workspace in R12 BL win_removeUnknownHandler ;Deregister the handler MOVVC R0,#2 ;Call every TV frame ADRVC R1,rgb__idles ;Point to the idle handler BLVC idle_removeHandler ;Deregister that too LDMFD R13!,{R0-R3,PC}^ ;And return to caller LTORG ;----- Icon numbers --------------------------------------------------------- rgbIcon__square EQU 0 ;The main colour square rgbIcon__slide1 EQU 1 ;The x slider (slider 1) rgbIcon__slide2 EQU 2 ;The y slider (slider 2) rgbIcon__slide3 EQU 3 ;The z slider (slider 3) rgbIcon__radioR EQU 4 ;The `Red' radio button rgbIcon__writeR EQU 5 ;The `Red' writable area rgbIcon__upR EQU 6 ;The `Red' up arrow button rgbIcon__downR EQU 7 ;The `Red' down arrow button rgbIcon__radioG EQU 9 ;The `Green' radio button rgbIcon__writeG EQU 10 ;The `Green' writable area rgbIcon__upG EQU 11 ;The `Green' up arrow button rgbIcon__downG EQU 12 ;The `Green' down arrow buttn rgbIcon__radioB EQU 14 ;The `Blue' radio button rgbIcon__writeB EQU 15 ;The `Blue' writable area rgbIcon__upB EQU 16 ;The `Blue' up arrow button rgbIcon__downB EQU 17 ;The `Blue' down arrow button rgbIcon__wCols EQU 20 ;Base of the WIMP colours ;----- That's all, folks ---------------------------------------------------- END