; ; hsv.s ; ; HSV functions (TMA) ; ; © 1994 Straylight ; ;----- Standard header ------------------------------------------------------ GET libs:header GET libs:swis ;----- External dependencies ------------------------------------------------ GET sapphire:dbox GET sapphire:divide GET sapphire:fixedPt GET sapphire:screen GET sapphire:sqrt GET sapphire:dbx.dbx GET sapphire:string GET sapphire:note GET sapphire:_cs.kernel GET sapphire:_cs.vars ;----- Main code ------------------------------------------------------------ AREA |Sapphire$$Code|,CODE,READONLY ; --- hsv_open --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Called by the colour picker EXPORT hsv_open hsv_open ROUT STMFD R13!,{R1-R3,R14} ;Stack the link register ADR R0,hsv_dbName ;Point to dialogue box name BL dbox_create ;Create the dialogue box ; --- TEMPORARY CODE --- LDMVSFD R13!,{R1-R3,PC} ;Return to caller ADR R1,hsv__dbh MOV R2,R10 MOV R3,R12 BL dbox_eventHandler LDMVSFD R13!,{R1-R3,PC} ;Return to caller ADR R1,hsv__dbxDef ;Point to the control defn BL dbx_declare ;Declare it to dbx nicely LDMFD R13!,{R1-R3,PC} ;Return to caller hsv_dbName DCB "hsv",0 hsv__dbxDef CONTROL 0,hsvCircle,R10,0,0 ECTRL DBXEND LTORG hsv__dbh ROUT CMP R0,#csEvent__close ;Is this a close event? MOVNES PC,R14 ;No -- return then STMFD R13!,{R0,R14} ;Save registers MOV R0,R9 BL dbox_destroy LDMFD R13!,{R0,PC}^ LTORG ; --- hsv_plotCircle --- ; ; On entry: R0 == x coord of centre of circle to plot ; R1 == y coord of centre of circle to plot ; R2 == x step (in OS units, must be power of 2) ; R3 == y step (in OS units, must be power of 2) ; R4 == value coordinate (in 16.16 form) ; R5 == pointer to graphics rectangle block ; ; On exit: -- ; ; Use: Plots an HSV colour circle at the position specified. ; This should look really pretty as long as you're not using ; RISC OS 2 :-(. EXPORT hsv_plotCircle hsv_plotCircle ROUT STMFD R13!,{R0-R10,R12,R14} ;Save a job lot of regs MOV R12,R5 ;Keep pointer to graphics blk ; --- Set up the radius value --- MOV R14,R4,LSR #9 ;Calculate the radius value MUL R10,R14,R14 ;Now square it and keep it ; --- Work out the pixel sizes --- BL screen_getInfo ;Find out about the screen LDMIA R0,{R6,R7} ;Load the eign factors MOV R14,#1 ;We're going to shift this MOV R6,R14,LSL R6 ;Calculate the x pixel size MOV R7,R14,LSL R7 ;And the y pixel size STMFD R13!,{R6,R7} ;Save these for later use ; --- Start the main loop off --- LDR R9,[R12,#12] ;Get top of the rectangle SUB R9,R9,R1 ;Subtract the circle centre CMP R9,#127 ;Is the rectangle too high? MOVGT R9,#127 ;Yes -- start at circle top SUB R14,R3,#1 ;Turn ystep into bitmask BIC R9,R9,R14 ;And align to multiple nicely ; --- Get start x position into R1 --- LDR R1,[R12,#0] ;Get left hand side of area LDR R14,[R13,#8] ;Load the centre position SUB R1,R1,R14 ;Subtract to get offset CMP R1,#-128 ;Is it too far to the left? MOVLT R1,#-128 ;Yes -- fix it up SUB R14,R2,#1 ;Turn xstep into bitmask BIC R1,R1,R14 ;Align to step value nicely ; --- Get finish x position into R4 --- LDR R4,[R12,#8] ;Get the right hand side pos LDR R0,[R13,#8] ;Load the x centre position SUB R4,R4,R0 ;Convert to offset CMP R4,#128 ;Is this off the right side? MOVGT R4,#128 ;Yes -- stop being silly then ; --- And now get finish y position into R5 --- LDR R5,[R12,#4] ;Get the bottom pos LDR R0,[R13,#12] ;Load the y centre position SUB R5,R5,R0 ;Convert to offset SUB R5,R5,R3 ;Get the bottom of the sqr CMP R5,#-128 ;Is this off the bottom? MOVLT R5,#-128 ;Yes -- don't be silly then ; --- Plot a row --- 00 MOV R8,R1 ;Start at beginning of row ; --- Plot this rectangle --- 01 LDMIA R13,{R6,R7} ;Load pixel widths and things STMFD R13!,{R1-R5,R8,R9} ;Save some useful things SUB R4,R2,R6 ;xstep-dx SUB R5,R3,R7 ;ystep-dy ; --- Calculate minx and maxx for given rectangle --- MUL R14,R9,R9 ;Get y^2 SUB R6,R10,R14 ;Calculate minx ADD R0,R9,R5 ;y+ystep-dy MUL R14,R0,R0 ;(y+ystep-dy)^2 SUB R7,R10,R14 ;Calculate maxx ; --- Calculate various square values of x --- MUL R0,R8,R8 ;Get x^2 ADD R14,R8,R2 ;Get x+xstep MUL R1,R14,R14 ;And square that too CMP R8,#0 ;Is x negative RSBLT R0,R0,#0 ;Yes -- make R0 -ve RSBLT R1,R1,#0 ;...and make R1 -ve ; --- Swap minx and maxx if we need to --- MOV R14,#0 ;Clear our `swap' flag CMP R8,#0 ;Is x < 0 EORGE R14,R14,#1 ;No -- toggle swap flag RSBLT R6,R6,#0 ;Yes -- make it -ve RSBLT R7,R7,#0 ;...and that too CMP R9,#0 ;Is y < 0 EORLT R14,R14,#1 ;Yes -- toggle swap flag TST R14,#1 ;Do we need to swap? EORNE R6,R6,R7 ;Yes -- swap them round EORNE R7,R6,R7 EORNE R6,R6,R7 ; --- Is the rectangle outside the circle --- CMP R1,R6 ;Is (x+xstep)^2=maxx? CMPGE R8,#0 ;Yes -- is x>=0 BLT %20hsv_plotCircle ;No -- Try an edge rectangle ; --- Plot a blank square --- 10 MOV R0,#1 ;Wimp colour 1 SWI Wimp_SetColour ;Set the colour BL hsv__plotRectangle ;Plot the rectangle B %70hsv_plotCircle ;And branch to the end ; --- Is the rectangle on the circle edge? --- 20 CMP R8,#0 ;Is x < 0? CMPLT R0,R7 ;Is x^2=0 CMPGE R1,R6 ;Is (x+xstep)>=minx BLT %40hsv_plotCircle ;No -- plot an entire square ; --- Plot an edge square then --- 25 MOV R0,#1 ;Wimp colour 1 SWI Wimp_SetColour ;Set the colour BL hsv__plotRectangle ;Plot the rectangle BL hsv__setColour ;Set the correct colour ADD R7,R9,R5 ;Our final loop value ADD R14,R13,#36 ;Point to centre coords LDMIA R14,{R3,R5} ;Get the centre coordinates 30 MUL R14,R9,R9 ;y^2 SUBS R0,R10,R14 ;Get r^2-y^2 BLT %35hsv_plotCircle ;Yes -- go round loop again ; BL sqrt ;Calculate the square root CMP R8,#0 ;Is x<0? RSBLT R1,R0,#0 ;Yes -- get xstart pos ADDLT R6,R8,R4 ;...and xend position MOVGE R1,R8 ;No -- this xstart LDRGE R6,[R13,#28] ;...get dx SUBGE R6,R0,R6 ;...and calc xend pos CMP R1,R6 ;Is there anything to plot? BGT %35hsv_plotCircle ;No -- skip this line out ADD R1,R1,R3 ;x0 ADD R2,R9,R5 ;y0 MOV R0,#4 ;Move absolute SWI OS_Plot ;Do the move MOV R0,#5 ;Plot solid line absolute ADD R1,R3,R6 ;x1 ADD R2,R9,R5 ;y1 SWI OS_Plot ;Do the move 35 LDR R14,[R13,#32] ;Get dy ADD R9,R9,R14 ;Increment y value CMP R9,R7 ;Are we at the end? BLE %30hsv_plotCircle ;And keep ploting lines B %70 ;Finished this square ; --- Now plot an entire coloured square --- 40 BL hsv__setColour ;Set the colour BL hsv__plotRectangle ;Plot it then ; --- Find which square to do next --- 70 LDMFD R13!,{R1-R5,R8,R9} ;Get back registers ADD R8,R8,R2 ;Increment R8 nicely CMP R8,R4 ;Have we finished a row? BLT %01hsv_plotCircle ;No -- do some more then SUB R9,R9,R3 ;Move down to the next row CMP R9,R5 ;Have we finished it yet? BGE %00hsv_plotCircle ;No -- do the next row ; --- We did it then! --- ADD R13,R13,#8 ;Skip past variable area LDMFD R13!,{R0-R10,R12,PC}^ ;Jubilations and things LTORG ; --- hsv__plotRectangle --- ; ; On entry: R4 == width ; R5 == height ; R8 == x offset from centre ; R9 == y offset from centre ; R13+36 centre coordinates ; ; On exit: R0-R2 corrupted hsv__plotRectangle ROUT ADD R0,R13,#36 ;Point to circle centre LDMIA R0,{R1,R2} ;Load the coordinates MOV R0,#4 ;Move cursor absolute ADD R1,R1,R8 ;To this x coord ADD R2,R2,R9 ;And this y coord SWI OS_Plot ;Do the move MOV R0,#97 ;Rectangle fill relative MOV R1,R4 ;This wide MOV R2,R5 ;This high SWI OS_Plot ;Plot the rectangle MOVS PC,R14 ;And return to caller LTORG ; --- hsv__setColour --- ; ; On entry: R0 == x coord ; R1 == y coord ; R10 == radius^2 ; R13+52 == value ; ; On exit: -- hsv__setColour ROUT STMFD R13!,{R0-R4,R14} ;Stack some registers BL fxp_pol ;Calculate hue MOV R3,R0 ;Preserve angle MUL R14,R1,R1 ;Get y^2 MUL R0,R2,R2 ;Get x^2 ADD R0,R0,R14 ;Add them MOV R1,R10 ;Get radius^2 MOV R0,R0,LSL#16 ;Prepare for division CMP R1,#0 ;Will we divide by 0? BLNE div_round ;No -- perform the division MOVEQ R0,#0 ;Yes -- make it 0 for luck MOV R1,R0 ;The saturation MOV R0,R3 ;Get hue back LDR R2,[R13,#76] ;Get value BL hsv_HSVToRGB ;Convert to RGB RSB R0,R0,R0,LSL#8 ;Multiple by 255 RSB R1,R1,R1,LSL#8 ;Multiple by 255 RSB R2,R2,R2,LSL#8 ;Multiple by 255 AND R0,R0,#&FF0000 ;Ensure it's 0-255 AND R1,R1,#&FF0000 ;Ensure it's 0-255 AND R2,R2,#&FF0000 ;Ensure it's 0-255 MOV R0,R0,LSR#8 ;Set up red component ORR R0,R0,R1 ;And green component ORR R0,R0,R2,LSL#8 ;And finally blue MOV R14,R0 ;Preserve R0 MOV R3,#&100 ;The colourTrans flags MOV R4,#0 ;GCOL action SWI XColourTrans_SetGCOL ;Set the colour MOVVS R3,#0 ;Try without dither MOVVS R0,R14 ;Get colour back SWIVS ColourTrans_SetGCOL ;Set the colour LDMFD R13!,{R0-R4,PC}^ ;Return to caller LTORG ; --- hsv__plot32k --- ; ; On entry: R0 == left hand side of colour square to plot ; R1 == bottom edge of colour square to plot ; R2 == pointer to graphics window block ; R3 == pointer to screen information block ; R7 == unlimited minimum x position to plot ; R8 == unlimited minimum y position to plot ; R9 == unlimited maximum x position to plot ; R10 == unlimited maximum y position to plot ; On stack: saved {R0-R12,R14} ; ; On exit: -- ; ; Use: Displays an HSV circle on the screen at a given location, ; in a 16bpp mode, using direct screen access. hsv__plot32k ROUT ; --- Limit the relative box positions --- ADD R4,R3,#screen_dx ;Find the pixel positions LDMIA R4,{R4,R5} ;Load them into registers CMP R7,#0 ;Is min x too small? MOVLT R7,#0 ;Yes -- raise it to 0 CMP R8,#0 ;Is min y too small? MOVLT R8,#0 ;Yes --- raise that too CMP R9,#256 ;Is the max x too large? MOVGT R9,#256 ;Yes -- reduce it then CMP R10,#256 ;Is the max y too large? MOVGT R10,#256 ;Yes -- reduce it then SUB R9,R9,R4 ;Make this inclusive SUB R10,R10,R5 ;Make this inclusive too ; --- Find address of thing on the screen --- MOV R5,R7 ;Remember left hand offset MOV R6,R10 ;And right hand one SUB R9,R9,R7 ;Work out width SUB R8,R10,R8 ;And height ADD R7,R7,R0 ;Work out left hand side ADD R10,R10,R1 ;And maximum y SUB R13,R13,#20 ;Space for our vdu vars ADR R0,hsv__vduVars ;Point to the var numbers MOV R1,R13 ;Point to our output block SWI OS_ReadVduVariables ;Get the values nicely ; --- Convert things to pixels sizes --- LDMIA R13!,{R3,R4} ;Load out eig factors MOV R7,R7,LSR R3 ;Convert left hand side MOV R8,R8,LSR R4 ;And height MOV R9,R9,LSR R3 ;The width too MOV R10,R10,LSR R4 ;And the top coord LDMIA R13!,{R0,R1,R2} ;Load other vdu vars SUB R14,R1,R10 ;Shift origin to top left MLA R0,R14,R2,R0 ;Work out address of row ADD R12,R0,R7,LSL #1 ;Work out left address ADD R11,R12,R9,LSL #1 ;Work out right hand side too MOV R9,R2 ;Put scan line width in R9 MOV R10,R8 ;And height in R10 SUB R8,R5,#128 ;Work out x start position SUB R7,R6,#128 ;And y start position MOV R14,#1 ;Get a useful value MOV R6,R14,LSL R3 ;x step MOV R5,R14,LSL R4 ;y step MOV R4,R8 ;Initial x value MOV R3,#&10000 ;Value ; --- Plot the circle then --- 10hsv__plot32k MOV R0,#0 ;Clear buffer register MOV R1,R12 ;Get the current address BL hsv__getColour32 ;Get the colour then TST R1,#2 ;Is this address aligned? BEQ %20hsv__plot32k ;Yes -- start at main loop LDR R14,[R1,#-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,[R1,#-2] ;And store in frame buffer B %25hsv__plot32k ;Jump to end of loop ; --- Now the main plotting loop --- 20hsv__plot32k TST R1,#2 ;Is this an odd address? STRNE R0,[R1,#-2] ;Yes -- done both half words 25hsv__plot32k ADD R1,R1,#2 ;Move onto next pixel ADD R8,R8,R6 ;Increment x position CMP R1,R11 ;Are we at the line end? BLLS hsv__getColour32 ;No -- get the colour then BLS %20hsv__plot32k ;...and go round for more ; --- We've finished; do we have a half word left over? --- 30hsv__plot32k TST R1,#2 ;Is the address odd? BEQ %35hsv__plot32k ;No -- jump ahead LDR R14,[R1,#-2] ;Yes -- read old word MOV R0,R0,LSR #16 ;Put buffer value in low hw MOV R14,R14,LSR #16 ;Shift down screen value too ORR R14,R0,R14,LSL #16 ;Build up correct word STR R14,[R1,#-2] ;Store this word away ; --- Move onto the next row --- 35hsv__plot32k ADD R12,R12,R9 ;Move left address down ADD R11,R11,R9 ;And the right address SUB R7,R7,R5 ;Decrement the y position MOV R8,R4 ;Initial start x position SUBS R10,R10,#1 ;Decrement the line count BCS %10hsv__plot32k ;And keep on going LDMFD R13!,{R0-R12,PC}^ ;Return to caller LTORG hsv__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 ; --- hsv__getColour32 --- ; ; On entry: R0 == colour word so far ; R1 == current screen address ; R3 == value (16.16) ; R7 == y position ; R8 == x position ; ; On exit: R0 == updated colour word ; ; ; Use: Determines the colour of the pixel at the given position ; for a 32k colour mode hsv__getColour32 ROUT STMFD R13!,{R1-R5,R14} ;Stack some regsiters MOV R5,R0 ;Look after old colour MUL R2,R7,R7 ;Get y^2 MUL R14,R8,R8 ;Get x^2 ADD R2,R2,R14 ;Get x^2+y^2 CMP R2,#&4000 ;Is this in range? BCS %50hsv__getColour32 ;No -- do really clever stuff MOV R0,R8 ;Put x position in R0 MOV R1,R7 ;And x position in R1 BL fxp_pol ;Calculate hue MOV R4,R0 ;Preserve angle MOV R0,R2 ;x^2 + y^2 MOV R1,#&4000 ;Get radius^2 MOV R0,R0,LSL#16 ;Prepare for division CMP R1,#0 ;Will we divide by 0? BLNE div_round ;No -- perform the division MOVEQ R0,#0 ;Yes -- make it 0 for luck MOV R1,R0 ;The saturation MOV R0,R4 ;Get hue back MOV R2,R3 ;Put value in R2 BL hsv_HSVToRGB ;Convert to RGB RSB R0,R0,R0,LSL#5 ;Multiple by 31 RSB R1,R1,R1,LSL#5 ;Multiple by 31 RSB R2,R2,R2,LSL#5 ;Multiple by 31 AND R0,R0,#&1F0000 ;Ensure it's 0-31 AND R1,R1,#&1F0000 ;Ensure it's 0-31 AND R2,R2,#&1F0000 ;Ensure it's 0-31 ORR R14,R0,R1,LSL #5 ;Red and green ORR R14,R14,R2,LSL #10 ;...blue ORR R0,R14,R5,LSR #16 ;Return colour number LDMFD R13!,{R1-R5,PC}^ ;Return to caller ; --- Position is out of range --- 50 LDR R14,[R1,#0] ;Load halfword at address MOV R14,R14,LSL #16 ;Put it into top halfword ORR R0,R14,R5,LSR #16 ;Build up new colour value LDMFD R13!,{R1-R5,PC}^ ;And return to caller LTORG ; --- hsv__plot16m --- ; ; On entry: R0 == left hand side of colour square to plot ; R1 == bottom edge of colour square to plot ; R2 == pointer to graphics window block ; R3 == pointer to screen information block ; R7 == unlimited minimum x position to plot ; R8 == unlimited minimum y position to plot ; R9 == unlimited maximum x position to plot ; R10 == unlimited maximum y position to plot ; On stack: saved {R0-R12,R14} ; ; On exit: -- ; ; Use: Displays an HSV circle on the screen at a given location, ; in a 32bpp mode, using direct screen access. hsv__plot16m ROUT ; --- Limit the relative box positions --- ADD R4,R3,#screen_dx ;Find the pixel positions LDMIA R4,{R4,R5} ;Load them into registers CMP R7,#0 ;Is min x too small? MOVLT R7,#0 ;Yes -- raise it to 0 CMP R8,#0 ;Is min y too small? MOVLT R8,#0 ;Yes --- raise that too CMP R9,#256 ;Is the max x too large? MOVGT R9,#256 ;Yes -- reduce it then CMP R10,#256 ;Is the max y too large? MOVGT R10,#256 ;Yes -- reduce it then SUB R9,R9,R4 ;Make this inclusive SUB R10,R10,R5 ;Make this inclusive too ; --- Find address of thing on the screen --- MOV R5,R7 ;Remember left hand offset MOV R6,R10 ;And right hand one SUB R9,R9,R7 ;Work out width SUB R8,R10,R8 ;And height ADD R7,R7,R0 ;Work out left hand side ADD R10,R10,R1 ;And maximum y SUB R13,R13,#20 ;Space for our vdu vars ADR R0,hsv__vduVars ;Point to the var numbers MOV R1,R13 ;Point to our output block SWI OS_ReadVduVariables ;Get the values nicely ; --- Convert things to pixels sizes --- LDMIA R13!,{R3,R4} ;Load out eig factors MOV R7,R7,LSR R3 ;Convert left hand side MOV R8,R8,LSR R4 ;And height MOV R9,R9,LSR R3 ;The width too MOV R10,R10,LSR R4 ;And the top coord LDMIA R13!,{R0,R1,R2} ;Load other vdu vars SUB R14,R1,R10 ;Shift origin to top left MLA R0,R14,R2,R0 ;Work out address of row ADD R12,R0,R7,LSL #2 ;Work out left address ADD R11,R12,R9,LSL #2 ;Work out right hand side too MOV R9,R2 ;Put scan line width in R9 MOV R10,R8 ;And height in R10 SUB R8,R5,#128 ;Work out x start position SUB R7,R6,#128 ;And y start position MOV R14,#1 ;Get a useful value MOV R6,R14,LSL R3 ;x step MOV R5,R14,LSL R4 ;y step MOV R4,R8 ;Initial x value MOV R3,#&10000 ;Value ; --- Plot the circle then --- 10hsv__plot16m MOV R1,R12 ;Get the current address ; --- Now the main plotting loop --- 20hsv__plot16m BL hsv__getColour16 ;Get the colour then STR R0,[R1],#4 ;Yes -- done both half words 25hsv__plot16m ADD R8,R8,R6 ;Increment x position CMP R1,R11 ;Are we at the line end? BLS %20hsv__plot16m ;...and go round for more ; --- Move onto the next row --- 30hsv__plot16m ADD R12,R12,R9 ;Move left address down ADD R11,R11,R9 ;And the right address SUB R7,R7,R5 ;Decrement the y position MOV R8,R4 ;Initial start x position SUBS R10,R10,#1 ;Decrement the line count BCS %10hsv__plot16m ;And keep on going LDMFD R13!,{R0-R12,PC}^ ;Return to caller LTORG ; --- hsv__getColour16-- ; ; On entry: R3 == value (16.16) ; R7 == y position ; R8 == x position ; ; On exit: R0 == updated colour word ; ; Use: Determines the colour of the pixel at the given position ; for a 32m colour mode hsv__getColour16 ROUT STMFD R13!,{R1-R4,R14} ;Stack some regsiters MUL R2,R7,R7 ;Get y^2 MUL R4,R8,R8 ;Get x^2 ADD R2,R2,R4 ;Get x^2+y^2 CMP R2,#&4000 ;Is this in range? LDRCS R0,[R1,#0] ;No -- load previous colour LDMCSFD R13!,{R1-R4,PC}^ ;And return to caller MOV R0,R8 ;Put x position in R0 MOV R1,R7 ;And x position in R1 BL fxp_pol ;Calculate hue MOV R4,R0 ;Preserve angle MOV R0,R2 ;x^2 + y^2 MOV R1,#&4000 ;Get radius^2 MOV R0,R0,LSL#16 ;Prepare for division CMP R1,#0 ;Will we divide by 0? BLNE div_round ;No -- perform the division MOVEQ R0,#0 ;Yes -- make it 0 for luck MOV R1,R0 ;The saturation MOV R0,R4 ;Get hue back MOV R2,R3 ;Put value in R2 BL hsv_HSVToRGB ;Convert to RGB RSB R0,R0,R0,LSL#8 ;Multiple by 255 RSB R1,R1,R1,LSL#8 ;Multiple by 255 RSB R2,R2,R2,LSL#8 ;Multiple by 255 AND R0,R0,#&FF0000 ;Ensure it's 0-255 AND R1,R1,#&FF0000 ;Ensure it's 0-255 AND R2,R2,#&FF0000 ;Ensure it's 0-255 ORR R0,R2,R0,LSR #16 ;Get red & blue components ORR R0,R0,R1,LSR #8 ;And green LDMFD R13!,{R1-R4,PC}^ ;Return to caller LTORG ; --- hsv__plotCircle --- ; ; On entry: R0 == left hand side of colour square to plot ; R1 == bottom edge of colour square to plot ; R2 == pointer to graphics window block ; ; On exit: -- ; ; Use: Dispatches to the most suitable hsv plotting routine for ; the given mode. hsv__plotCircle ROUT STMFD R13!,{R0-R12,R14} ;Save lots of registers ; --- Work out the minimum coordinates --- LDMIA R2,{R7,R8,R9,R10} ;Load the coordinates out SUB R7,R7,R0 ;Translate min x to relative SUB R8,R8,R1 ;Translate min y too SUB R9,R9,R0 ;Translate max x too SUB R10,R10,R1 ;Translate max y ; --- Try to dispatch --- MOV R4,R0 ;Look after left hand side BL screen_getInfo ;Get screen info block MOV R3,R0 ;Put it in R3 MOV R0,R4 ;And get left hand side back LDR R14,[R3,#screen_bpp] ;Load current bits/pixel CMP R14,#16 ;Is this a 32K mode? BEQ hsv__plot32k ;Yes -- well, go to it CMP R14,#32 ;Is this a 32K mode? BEQ hsv__plot16m LDMFD R13!,{R0-R12,PC}^ ;Return to caller LTORG ; --- The dbx control --- hsvCircle ROUT DCD 0,0 DCD dbxMask_redraw+dbxMask_click CMP R0,#dbxEvent_click BEQ %10 STMFD R13!,{R0-R2,R10,R14} ;Stack some registers MOV R10,R8 ;Put dbox data in R10 MOV R0,R2 ;Put bottom left in R0 MOV R1,R3 ;And bottom right in R1 MOV R2,R6 ;Put graphics rectangle in R2 BL hsv__plotCircle ;Plot the circle then LDMFD R13!,{R0-R2,R10,PC}^ ;Return to caller 10 STMFD R13!,{R0-R5,R14} MOV R0,R10 BL dbx_controlBBox SUB R4,R4,R2 SUB R5,R5,R3 ADD R0,R2,R4,LSR #1 ADD R1,R3,R5,LSR #1 MOV R2,#128 SWI Constrain_Disc LDMFD R13!,{R0-R5,PC}^ LTORG [ 0=1 ; --- sqrt --- ; ; On entry: R0 == number to find square root of ; ; On exit: R0 == square root of number passed in ; ; Use: Calculates the square root of the number passed to ; the nearest integer sqrt ROUT STMFD R13!,{R1-R5,R14} ;Stack some registers MOV R4,R0,LSR#2 ;Get an approximation MOV R3,#-1 ;The old value MOV R2,R0 ;Keep this value MOV R5,#10 ;Maximum number of iterations 00sqrt MOV R0,R2,ASR #1 ;Divide number to squareroot MOVS R1,R4 ;By 2*our approximation BEQ %01sqrt ;Divide by 0 -- leave now BL div_round ;Round result to nearest ADD R4,R0,R4,ASR #1 ;Add this to x/2 SUBS R5,R5,#1 ;Decrement iteration count BEQ %01sqrt ;Too low -- skip to end CMP R4,R3 ;Is solution same as last? MOVNE R3,R4 ;No -- remember result BNE %00sqrt ;...and keep trying 01sqrt MOV R0,R4 ;Return root in R0 LDMFD R13!,{R1-R5,PC}^ ;Return to caller LTORG ] ; --- HSV -> RGB conversion --- ; --- div60 --- ; ; On entry: R0 == integer to divide ; ; On exit: R0 == quotient after division by 60 ; R1 == remainder after division by 60 ; ; Use: Divides an integer very quickly by 60. ; ; [Generated by Straylight divc] div60 ROUT STMFD R13!,{R2,R14} MOVS R2,R0 RSBMI R0,R0,#0 MOV R1,R0 ADD R0,R0,R0,LSR#4 ADD R0,R0,R0,LSR#8 ADD R0,R0,R0,LSR#16 MOV R0,R0,LSR #6 RSB R14,R0,R0,LSL#4 MOV R14,R14,LSL#2 SUB R1,R1,R14 SUBS R1,R1,#60 ADDGE R0,R0,#1 ADDLT R1,R1,#60 CMP R2,#0 RSBMI R0,R0,#0 RSBMI R1,R1,#0 LDMFD R13!,{R2,PC}^ LTORG ; --- hsv_HSVToRGB --- ; ; On entry: R0 == hue ; R1 == saturation ; R2 == value ; ; On exit: R0 == red ; R1 == green ; R2 == blue ; ; Use: Convert a colour in HSV to the equivalent in RGB notation. ; All number are taken in 16.16 fixed point form. RGB values ; range from 0 to 1 on output. hsv_HSVToRGB ROUT STMFD R13!,{R3-R7,R14} ;Stack some registers CMP R0,#(360<<16) ;Is hue 360? MOVEQ R0,#0 ;Yes -- make it 0 MOV R3,R1 ;Put saturation in R3 BL div60 ;Divide hue by 60 BIC R1,R0,#&FF0000 ;Get fractional part in R1 MOV R0,R0,LSR#16 ;And integer part in R0 MOV R4,R2,LSR#8 ;For multiplication RSB R5,R3,#1<<16 ;1-saturation (16.16 form) MOV R5,R5,LSR#8 ;Shift for division MUL R5,R4,R5 ;Minimum=value*(1-saturation) MOV R14,R3,LSR#8 ;Saturation >> 8 MOV R6,R1,LSR#8 ;Fractional >> 8 MUL R6,R14,R6 ;Saturation*fractional RSB R6,R6,#1<<16 ;1-(previous result) MOV R6,R6,LSR#8 ;Prepare for multiplication MUL R6,R4,R6 ;Inverse1=value*(prev result) RSB R7,R1,#1<<16 ;1-fractional MOV R7,R7,LSR#8 ;Prepare for multiplication MUL R7,R14,R7 ;Saturation*(1-fractional) RSB R7,R7,#1<<16 ;1-(sat*(1-fractional)) MOV R7,R7,LSR#8 ;Prepare for multiplication MUL R7,R4,R7 ;Value*(1-(sat*(1-frac))) ; --- Find out which section number we are in --- CMP R0,#0 ;Section 0? BNE %10hsv_HSVToRGB ;No -- try next one MOV R0,R2 ;Red = value MOV R1,R7 ;Green = inverse2 MOV R2,R5 ;Blue = minimum LDMFD R13!,{R3-R7,PC}^ ;Return to caller 10hsv_HSVToRGB CMP R0,#1 ;Section 1? BNE %20hsv_HSVToRGB ;No -- try next one MOV R0,R6 ;Red = inverse1 MOV R1,R2 ;Green = value MOV R2,R5 ;Blue = minimum LDMFD R13!,{R3-R7,PC}^ ;Return to caller 20hsv_HSVToRGB CMP R0,#2 ;Section 2? BNE %30hsv_HSVToRGB ;No -- try next one MOV R0,R5 ;Red = minimum MOV R1,R2 ;Green = value MOV R2,R7 ;Blue = inverse2 LDMFD R13!,{R3-R7,PC}^ ;Return to caller 30hsv_HSVToRGB CMP R0,#3 ;Section 3? BNE %40hsv_HSVToRGB ;No -- try next one MOV R0,R5 ;Red = minimum MOV R1,R6 ;Green = inverse1 LDMFD R13!,{R3-R7,PC}^ ;Return to caller 40hsv_HSVToRGB CMP R0,#4 ;Section 0? BNE %50hsv_HSVToRGB ;No -- try next one MOV R0,R7 ;Red = inverse2 MOV R1,R5 ;Green = minimum LDMFD R13!,{R3-R7,PC}^ ;Return to caller 50hsv_HSVToRGB CMP R0,#5 ;Section 0? BNE %60hsv_HSVToRGB ;No -- try next one MOV R0,R2 ;Red = value MOV R1,R5 ;Green = minimum MOV R2,R6 ;Blue = inverse1 LDMFD R13!,{R3-R7,PC}^ ;Return to caller 60hsv_HSVToRGB ADR R0,convert__error ;Point to the error message SWI OS_GenerateError ;And generate an error convert__error DCD 1 DCB "Fatal error: hsv_HSVToRGB -- section >5 reached",0 LTORG ;----- Workspace layout ----------------------------------------------------- AREA |Sapphire$$LibData|,CODE,READONLY DCD 0 DCD 0 DCD 0 DCD 0 ;-- That's all, folks ------------------------------------------------------- END