; ; sprite.s ; ; Nice operations on sprites ; ; © 1994-1998 Straylight ; ;----- Licensing note ------------------------------------------------------- ; ; This file is part of Straylight's Sapphire library. ; ; Sapphire is free software; you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation; either version 2, or (at your option) ; any later version. ; ; Sapphire is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with Sapphire. If not, write to the Free Software Foundation, ; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;----- Standard header ------------------------------------------------------ GET libs:header GET libs:swis ;----- External dependencies ------------------------------------------------ GET sapphire:resspr GET sapphire:screen ;----- Main code ------------------------------------------------------------ AREA |Sapphire$$Code|,CODE,READONLY ; --- sprite_op --- ; ; On entry: R0,R2-R7 == SpriteOp parameters (R1 set up here) ; ; On exit: Registers and flags altered as for the SpriteOp ; ; Use: Performs an OS_SpriteOp with the given arguments, using ; the appication's Sprites resource as the sprite area. EXPORT sprite_op sprite_op ROUT STMFD R13!,{R0,R14} ;Stack some registers ; --- Get the current resource sprite area --- BL resspr_area ;Get area in R0 MOV R1,R0 ;Put it in R1 LDMFD R13!,{R0} ;Get the SpriteOp back ; --- Is it the WIMP sprite area (Yrggg...) --- CMP R1,#1 ;Is it WIMP area? BEQ %00sprite_op ;Yes -- deal with it ; --- We must be using the user sprite area --- ORR R0,R0,#&100 ;Use user area SWI XOS_SpriteOp ;Do the SpriteOp LDMFD R13!,{PC} ;And return to the user ; --- Use the WIMP sprite area --- 00sprite_op SWI XWimp_SpriteOp ;Do SpriteOp on WIMP area LDMFD R13!,{PC} ;And return to the user LTORG ; --- sprite_getTable --- ; ; On entry: R0 == pointer to a sprite ; R1 == pointer to buffer for translate table ; ; On exit: -- ; ; Use: Creates a colour translate table for the given sprite in ; the specified buffer. ; ; If you have a sprite name but no pointer, use OS_SpriteOp ; 24 to find the pointer -- this will make further sprite ops ; on the sprite much quicker. EXPORT sprite_getTable sprite_getTable ROUT STMFD R13!,{R0-R9,R14} ;Save some registers MOV R7,R0 ;Keep the sprite pointer MOV R8,R1 ;Keep the buffer pointer ; --- Find out how many colours the sprite has --- MOV R2,R7 ;Get the sprite pointer MOV R1,#&1000 ;No particular sprite area MOV R0,#40 ;Get sprite information ADD R0,R0,#512 ;Tell it I have a sprite ptr SWI OS_SpriteOp ;Read the sprite information MOV R0,R6 ;Get the sprite's mode MOV R1,#3 ;Read number of colours SWI OS_ReadModeVariable ;Read the mode value nicely MOV R9,R2 ;Keep number of colours ; --- Handle the Wimp palette --- ; ; If the sprite has 16 colours and no palette, we assume it ; should have the Wimp palette, and so use that. CMP R2,#15 ;Does it have 16 colours? LDREQ R14,[R7,#32] ;Get the sprite offset CMPEQ R14,#44 ;Is there no palette? BNE %10sprite_getTable ;No to either -- skip it out ; --- Read the WIMP palette, and use that --- SUB R13,R13,#80 ;Drop the stack pointer MOV R1,R13 ;Point to the block SWI Wimp_ReadPalette ;Read the Wimp palette MOV R0,R6 ;Source mode set up MOV R2,#-1 ;Use current mode MOV R3,#-1 ;Use current palette too MOV R4,R8 ;Create in caller's buffer SWI ColourTrans_SelectTable ;Set up the table nicely ADD R13,R13,#80 ;Restore the stack pointer B %90sprite_getTable ;And skip to the end ; --- Try and use the RISC OS 3 way --- 10 MOV R0,#&1000 ;No sprite area in particular MOV R1,R7 ;Point to my sprite MOV R2,#-1 ;Output in current mode MOV R3,#-1 ;And into current palette MOV R4,R8 ;Into the caller's buffer MOV R5,#1 ;And output a sprite table SWI XColourTrans_SelectTable ;Try and read the table BVC %90sprite_getTable ;If it worked, finish ; --- If the sprite has no palette, just assume default --- CMP R9,#15 ;Is the number of colours>16? BGT %15sprite_getTable ;Yes -- assume def palette LDR R14,[R7,#32] ;Get the sprite offset CMP R14,#44 ;Is there a palette? BNE %20sprite_getTable ;Yes -- handle it then 15 MOV R0,R6 ;Source mode set up MOV R1,#0 ;Assume default palette MOV R2,#-1 ;Use current mode MOV R3,#-1 ;Use current palette too MOV R4,R8 ;Create in caller's buffer SWI ColourTrans_SelectTable ;Set up the table nicely B %90sprite_getTable ;And skip to the end ; --- Read the palette from the sprite --- 20 ADD R0,R7,#44 ;Point to first palette entry SUB R13,R13,R9,LSL #2 ;And make space for palette MOV R1,R13 ;Point to palette buffer MOV R2,R9 ;Copy the colour count 25 LDR R14,[R0],#8 ;Load a palette word STR R14,[R1],#4 ;Save it into the buffer SUBS R2,R2,#1 ;Decrement the counter BGE %25sprite_getTable ;If more to do, go round MOV R0,R6 ;Source mode set up MOV R1,R13 ;Point to my nice palette MOV R2,#-1 ;Use current mode MOV R3,#-1 ;Use current palette too MOV R4,R8 ;Create in caller's buffer SWI ColourTrans_SelectTable ;Set up the table nicely ADD R13,R13,R9,LSL #2 ;Reclaim the stack again ; --- Return to caller --- 90 LDMFD R13!,{R0-R9,PC}^ ;Return to caller LTORG ; --- sprite_plot --- ; ; On entry: R0 == pointer to a sprite ; R1 == x coordinate to plot at ; R2 == y coordinate to plot at ; R3 == pointer to scale block, or 0 for 1:1 ; ; On exit: CS if the sprite was plotted OK, else CC ; ; Use: Plots a sprite on the screen. The scaling refers to the ; sprite proper: /this/ routine takes care of odd pixel ; sizes and things, so sprites don't appear squashed or ; stretched unless you really want them to. ; ; We return C clear on exit if we couldn't plot the sprite; ; typically this would be if the sprite's mode is undefined. EXPORT sprite_plot sprite_plot ROUT STMFD R13!,{R0-R9,R14} ;Save some registers CMP R3,#0 ;Has he given a scaling? ADREQ R3,sprite__scale ;No -- use our own one LDMIA R3,{R5-R8} ;Load the scaling out ; --- Fiddle with the scale factors --- MOV R3,R1 ;Remember this position MOV R4,R2 ;And this one please MOV R9,R0 ;Remember the sprite addr BL screen_getInfo ;Read the screen info ADD R14,R0,#screen_xEig ;Find the EIG factors LDMIA R14,{R0,R1} ;Load them out nicely MOV R7,R7,LSL R0 ;Scale down by this resn MOV R8,R8,LSL R1 ;So go and do that LDR R0,[R9,#40] ;Load the mode gadget MOV R1,#4 ;Read the x EIG factor SWI OS_ReadModeVariable ;Read that then BCS %90sprite_plot ;If it failed, return MOV R5,R5,LSL R2 ;Bump up the scaling by this MOV R1,#5 ;Read the y EIG factor SWI OS_ReadModeVariable ;Read that then BCS %90sprite_plot ;If it failed, return MOV R6,R6,LSL R2 ;Bump up the scaling again STMFD R13!,{R5-R8} ;Save them away for later ; --- Now read the translation table and plot --- MOV R0,R9 ;Point to the sprite MOV R1,R11 ;Build table in R11-space BL sprite_getTable ;Go and do that then MOV R0,#52 ;Put sprite scaled ORR R0,R0,#512 ;Use my pointed-at sprite MOV R1,#&1000 ;A bogus sprite area MOV R2,R9 ;Point to the sprite MOV R5,#8 ;Plot with a mask MOV R6,R13 ;Point to scale factors MOV R7,R11 ;And to the translate table SWI XOS_SpriteOp ;Plot and ignore error ADD R13,R13,#16 ;Restore stack pointer BVS %90sprite_plot ;If it failed, abort LDMFD R13!,{R0-R9,R14} ;Restore registers ORRS PC,R14,#C_flag ;And return to caller 90sprite_plot LDMFD R13!,{R0-R9,R14} ;Restore registers BICS PC,R14,#C_flag ;And return to caller sprite__scale DCD 1,1,1,1 LTORG ;----- That's all, folks ---------------------------------------------------- END