diff --git a/VersionASM b/VersionASM
index 0ab1bcf15354538eb510e63491b63d7023b85097..5d34d2e62aaec6a8dcaf881e1db19f8a19fd8c2f 100644
--- a/VersionASM
+++ b/VersionASM
@@ -11,13 +11,13 @@
                         GBLS    Module_HelpVersion
                         GBLS    Module_ComponentName
                         GBLS    Module_ComponentPath
-Module_MajorVersion     SETS    "5.19"
-Module_Version          SETA    519
+Module_MajorVersion     SETS    "5.20"
+Module_Version          SETA    520
 Module_MinorVersion     SETS    ""
-Module_Date             SETS    "09 Oct 2012"
-Module_ApplicationDate  SETS    "09-Oct-12"
+Module_Date             SETS    "28 Mar 2013"
+Module_ApplicationDate  SETS    "28-Mar-13"
 Module_ComponentName    SETS    "Wimp"
 Module_ComponentPath    SETS    "castle/RiscOS/Sources/Desktop/Wimp"
-Module_FullVersion      SETS    "5.19"
-Module_HelpVersion      SETS    "5.19 (09 Oct 2012)"
+Module_FullVersion      SETS    "5.20"
+Module_HelpVersion      SETS    "5.20 (28 Mar 2013)"
                         END
diff --git a/VersionNum b/VersionNum
index 56db1ffe22a5eeafad71de15ecc37ec4bdd4a1cc..83c46cc67fe8d02719c1e5592bd4310d1145db81 100644
--- a/VersionNum
+++ b/VersionNum
@@ -1,23 +1,23 @@
-/* (5.19)
+/* (5.20)
  *
  * This file is automatically maintained by srccommit, do not edit manually.
  * Last processed by srccommit version: 1.1.
  *
  */
-#define Module_MajorVersion_CMHG        5.19
+#define Module_MajorVersion_CMHG        5.20
 #define Module_MinorVersion_CMHG        
-#define Module_Date_CMHG                09 Oct 2012
+#define Module_Date_CMHG                28 Mar 2013
 
-#define Module_MajorVersion             "5.19"
-#define Module_Version                  519
+#define Module_MajorVersion             "5.20"
+#define Module_Version                  520
 #define Module_MinorVersion             ""
-#define Module_Date                     "09 Oct 2012"
+#define Module_Date                     "28 Mar 2013"
 
-#define Module_ApplicationDate          "09-Oct-12"
+#define Module_ApplicationDate          "28-Mar-13"
 
 #define Module_ComponentName            "Wimp"
 #define Module_ComponentPath            "castle/RiscOS/Sources/Desktop/Wimp"
 
-#define Module_FullVersion              "5.19"
-#define Module_HelpVersion              "5.19 (09 Oct 2012)"
-#define Module_LibraryVersionInfo       "5:19"
+#define Module_FullVersion              "5.20"
+#define Module_HelpVersion              "5.20 (28 Mar 2013)"
+#define Module_LibraryVersionInfo       "5:20"
diff --git a/s/Tiling b/s/Tiling
index bb85c250093bf92ab0684eb1db7ed47a68d50b14..b4f2d6ab4c61ade093ccd7b2d9b059001b26fa81 100644
--- a/s/Tiling
+++ b/s/Tiling
@@ -48,8 +48,6 @@ plotspritebackground
         wsaddr  R4,clipx0
         MOV     R14,PC
         MOV     PC,R1
-        NOP
-        NOP
         Pull    "R0-R5,PC"
 2
         TEQ     R0,#1                           ; colour 1
@@ -85,9 +83,9 @@ plotspritebackground
         LDR     R0,sprite_log2py
         STR     R0,tile_log2py
 
-        LDR     R14,needsfactors
+        LDRB    R14,sprite_needsfactors
         TEQ     R14,#0
-        ADRNE   R14,factors
+        ADRNE   R14,sprite_factors
 
         Push    R3
 
@@ -97,7 +95,7 @@ plotspritebackground
         STMIA   R14,{R0-R3}
         Pull    R3
 
-        LDR     R1,needsfactors                 ; needs preserving
+        LDRB    R1,sprite_needsfactors          ; needs preserving
         Push    R1
 
         B       %FT6
@@ -129,15 +127,16 @@ plotspritebackground
         MOV     R0,#0
         STR     R0,lengthflags                  ; spritename is a pointer
 
-
-        LDR     R0,tile_pixtable
-        LDR     R1,needsfactors                 ; needs preserving
+        LDRB    R1,sprite_needsfactors          ; needs preserving
         Push    R1
 
-        STR     R0,tile_temptab
-
         LDR     R0,tile_sc_block
-        STR     R0,needsfactors
+        TEQ     R0, #0
+        MOVNE   R0, #-1
+        STRB    R0,sprite_needsfactors
+
+        LDR     R0,tile_pixtable
+        STR     R0,tile_temptab
 
         LDR     R3,tile_width
         LDR     R4,tile_height
@@ -210,7 +209,7 @@ err2
         Pull    "x0-y1"
 
         Pull    R0
-        STR     R0,needsfactors
+        STRB    R0,sprite_needsfactors
 
         ADRL    R14,tile_log2px                         ; restore global tile info
         Pull    "R0-R3"
@@ -274,7 +273,7 @@ findwimptilesprite  Entry "R0-R1"
         STR     R3,tile_width
         STR     R4,tile_height
 
-        LDR     R1,needsfactors
+        LDRB    R1,sprite_needsfactors
         Push    "R2-R3"
 
         LDR     R2,tile_pixtable
@@ -284,7 +283,7 @@ findwimptilesprite  Entry "R0-R1"
 
         TEQ     R1,#0
 
-        ADRNE   R14,factors
+        ADRNE   R14,sprite_factors
 
         LDMNEIA R14,{R0-R3}
         MOVEQ   R0,#0
@@ -347,7 +346,7 @@ findwimpspritefordepth
 tile_putsprite
         Push    "R1-R7,LR"
 ;
-        LDR     R0,needsfactors
+        LDRB    R0,sprite_needsfactors
         TEQ     R0,#0                   ; do I need to translate
 ;
         MOVNE   R0,#SpriteReason_PutSpriteScaled
diff --git a/s/Tiling3D b/s/Tiling3D
index 07998987499f3ae4f4ff87763943630db36ea5c4..0856dda0b8a3aaa3bc0fc27d71777a8b2af0bb1a 100644
--- a/s/Tiling3D
+++ b/s/Tiling3D
@@ -345,12 +345,12 @@ get_tile_sprite_info
 		mov	r4,r4,LSL r0
 		str	r4,[r8,#TileInfo_Height]
 
-		ldr	r0,needsfactors
+		ldrb	r0,sprite_needsfactors
 		teq	r0,#0
 
 		moveq	r0,#-1						; if the scale factors are not needed then the first one is -1
 
-		adrne	r14,factors
+		adrne	r14,sprite_factors
 		ldmneia	r14,{r0-r3}
 
 		add	r14,r8,#TileInfo_ScaleFactors
diff --git a/s/Trace b/s/Trace
new file mode 100644
index 0000000000000000000000000000000000000000..614e6707a88295058cbc9a8b5fe72ab2bcdbf968
--- /dev/null
+++ b/s/Trace
@@ -0,0 +1,149 @@
+; Copyright 2013 Castle Technology Ltd
+;
+; Licensed under the Apache License, Version 2.0 (the "License");
+; you may not use this file except in compliance with the License.
+; You may obtain a copy of the License at
+;
+;     http://www.apache.org/licenses/LICENSE-2.0
+;
+; Unless required by applicable law or agreed to in writing, software
+; distributed under the License is distributed on an "AS IS" BASIS,
+; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+; See the License for the specific language governing permissions and
+; limitations under the License.
+;
+; > Trace
+
+; Some extra tracing routines by Jonathan. All preserve all registers and
+; all flags
+
+; HostFS_WriteC * &40102
+
+;---------------------------------------------------------------------------
+trace_char ROUT
+
+; R0 = character to trace
+
+        EntryS  "R0, R1, R2"
+
+        CMP     R0, #32
+        BLT     |trace_char: nonprintable character|
+        CMP     R0, #127
+        BGE     |trace_char: nonprintable character|
+
+|trace_char: printable character|
+        ;write character
+        SWI     HostFS_WriteC
+        ;if it's a backslash, write it again
+        CMP     R0, #"\\"
+        SWIEQ   HostFS_WriteC
+        B       |trace_char: exit|
+
+|trace_char: nonprintable character|
+        CMP     R0, #:CHR: 10
+        BNE     |trace_char: control character|
+
+|trace_char: linefeed|
+        SWI     HostFS_WriteC
+
+        MOV     R0, #:CHR: 13
+        SWI     HostFS_WriteC
+
+        B       |trace_char: exit|
+
+|trace_char: control character|
+        ;save the character
+
+        MOV     R1, R0
+        ADR     R2, |trace_char: digits|
+
+; R1 = character to trace
+; R2 -> representation table
+
+        MOV     R0, #"\\"
+        SWI     HostFS_WriteC
+
+        MOV     R0, #"x"
+        SWI     HostFS_WriteC
+
+        ;trace top nybble
+        MOV     R0, R1, LSR #4
+        LDRB    R0, [R2, R0]
+        SWI     HostFS_WriteC
+
+        ;trace bottom nybble
+        AND     R0, R1, #&F
+        LDRB    R0, [R2, R0]
+        SWI     HostFS_WriteC
+
+|trace_char: exit|
+        EXITS
+
+|trace_char: digits|
+        =     "0123456789ABCDEF"
+        ALIGN
+;---------------------------------------------------------------------------
+trace_string ROUT
+
+; R0 -> string to trace
+
+        EntryS  "R0, R1"
+
+        MOV     R1, R0
+; R1 -> string to trace
+
+        B       |trace_string: end loop|
+|trace_string: start loop|
+        BL      trace_char
+        ADD     R1, R1, #1
+|trace_string: end loop|
+        LDRB    R0, [R1]
+        CMP     R0, #:CHR: 0
+        BNE     |trace_string: start loop|
+
+        EXITS
+;---------------------------------------------------------------------------
+trace_decimal ROUT
+
+; R0 = integer to trace
+
+        EntryS  "R0, R1, R2"
+
+        SUB     SP, SP, #16
+        MOV     R1, SP
+        MOV     R2, #15
+        SWI     OS_ConvertInteger4
+
+        ;trace it
+        BL      trace_string
+        ADD     SP, SP, #16
+
+        EXIT
+;---------------------------------------------------------------------------
+trace_hex ROUT
+
+; R0 = integer to trace
+
+        Push    "R0, R1, R2, LR"
+
+        SUB     SP, SP, #16
+        MOV     R1, SP
+        MOV     R2, #15
+        SWI     OS_ConvertHex8
+
+        ;trace it
+        BL      trace_string
+        ADD     SP, SP, #16
+
+        Pull    "R0, R1, R2, PC",, ^
+;---------------------------------------------------------------------------
+trace_nl ROUT
+
+        EntryS  "R0"
+
+        MOV     R0, #:CHR: 10
+        BL      trace_char
+
+        EXITS
+
+        END
diff --git a/s/Wimp b/s/Wimp
index 31e1ba83f89019e9fcbec23345e9b44e2c349917..2d3e23f82bf9d1d89b5d75f564c88514e513a126 100644
--- a/s/Wimp
+++ b/s/Wimp
@@ -106,5 +106,8 @@ LoadWimpOptions SETS "GET Options.s.$Options"
         GET     Wimp10.s
         GET     NewSWIs.s
         GET     AutoScroll.s
+      [ debug
+        GET     Trace.s
+      ]
 
         END
diff --git a/s/Wimp01 b/s/Wimp01
index 139da39423c7826c24de03bbb003b1aa133449aa..5e0fa054a54d7812d66aa8eafb765fce1fc45469 100644
--- a/s/Wimp01
+++ b/s/Wimp01
@@ -850,6 +850,7 @@ plotsprCB               #       4       ; backdrop tiling CB
 ; these have moved!
 RAM_SWIEntry            #       12      ; 3 instructions for getting R12 back
 OScopy_ChangeDynamic    #       4       ; this must follow immediately
+longjumpSP              #       4       ; for cutting out the middle-man
 ROMstart                #       4       ; ROM base address
 ROMend                  #       4       ; ROM end address (inclusive)
 
@@ -949,7 +950,10 @@ gcolaction      #       1               ; used by Wimp_SetColour
 sysflags        #       1               ; actions on moving windows (drag?)
 memoryOK        #       1               ; flag for ChangeDynamicArea
 modechanged     #       1               ; flag set on mode change
-preservett      #       1               ; used to hang onto translation tables
+sprite_needsfactors  #  1               ; otherwise 1:1 scaling for this mode
+tsprite_needsfactors #  1               ; otherwise 1:1 scaling for this mode
+tsprite_needsregen   #  1               ; need to recalculate the tool sprite pixtrans
+selecttable_crit     #  1               ; ignore invalidate cache service calls if we're the cause
               [ ChildWindows
 openspending    #       1               ; whether we're in the middle of a set of opens
               ]
@@ -1059,7 +1063,6 @@ sender          #       4
 myref           #       4
 
 maxmenus        *       8
-longjumpSP      #       4               ; for cutting out the middle-man
 whichmenu       #       4
 menus_temporary #       4               ; if set, Wimp_Poll kills the menus
 menuhandle      #       4
@@ -1234,34 +1237,41 @@ lastmode_x1     #       4               ; (xwindlimit+1) * px for previous mode
 lastmode_y1     #       4               ; (ywindlimit+1) * py for previous mode
 forceflags      #       4               ; for putting windows back
 
-lastmode        #       4
+ditheringflag   #       4               ; flag to control dithering
+
+sprite_lastmode #       4
 sprite_log2bpp  #       4               ; for mode-independent sprite plotting
 sprite_log2px   #       4
 sprite_log2py   #       4
-needsfactors    #       4
+tsprite_lastmode #      4
+tsprite_log2bpp  #      4               ; for mode-independent toolsprite plotting
+tsprite_log2px   #      4
+tsprite_log2py   #      4
            ALIGNHASH    16
-factors         #       16
-
-ditheringflag   #       4               ; flag to control dithering
+sprite_factors  #       16
+tsprite_factors #       16
 
-usephyspaltable #       4               ; use the physical palette table
 physpaltable    #       4*16            ; secondary palette table (disconnected from Wimp jobbie)
+temppaltable    #       4*16            ; temporary store for a palette
+usephyspaltable #       4               ; use the physical palette table
 
 transtable1     #       2               ; 1bpp mapping from wimp -> sprite pixels
 transtable2     #       4               ; 2bpp     ---------- "" ------------
 transtable4     #       16              ; 4bpp     ---------- "" ------------
-        ALIGNHASH       4
+        ALIGNHASH       16
+
+selecttable_args #      4*6             ; parameters used for the last sprite select table call
 
-pixtable_params #       4*6             ; parameters used for the select table call
 pixtable_at     #       4
 pixtable_size   #       4               ; size and position of pixtrans table currently setup
 
-temppaltable    #       4*16            ; temporary store for a palette
-
 list_at         #       4               ; head of sprite cache list
 list_size       #       4               ; size of buffer claimed
 list_end        #       4               ; end of list used for chop
 
+tpixtable_at    #       4
+tpixtable_size  #       4               ; size and position of tool pixtrans table currently setup
+
         [ windowsprite :LAND: :LNOT: ThreeDPatch
 tile_sc_block   #       16
 tile_log2px     #       4
@@ -1529,8 +1539,7 @@ errordynamic    *       errorbuffer+4   ; put these after stashed PC
 errordynamicsize *      ?errorbuffer-4
 stackspace      #       0               ; temporary stack for debugging!
 
-tools_area      #       4               ; area for tools list
-tools_trans_size #      4               ; size of last tools_trans
+tool_list_backup #      4               ; backup copy of tool_list
 copyerror       #       240             ; copy of error block
 greys_mode       #      1               ; last grey mode.
 last_greys      #       1               ; previous greys mode
@@ -1594,6 +1603,8 @@ maxwork         *       :INDEX:@
                 ! 0,    "Free pool              = R12+&" :CC: :STR: :INDEX: freepool
                 ! 0,    "#pixtable_at           = R12+&" :CC: :STR: :INDEX: pixtable_at
                 ! 0,    "#pixtable_size         = R12+&" :CC: :STR: :INDEX: pixtable_size
+                ! 0,    "#tpixtable_at          = R12+&" :CC: :STR: :INDEX: tpixtable_at
+                ! 0,    "#tpixtable_size        = R12+&" :CC: :STR: :INDEX: tpixtable_size
                 ! 0,    "#list_at               = R12+&" :CC: :STR: :INDEX: list_at
                 ! 0,    "#list_size             = R12+&" :CC: :STR: :INDEX: list_size
                 ! 0,    "#list_end              = R12+&" :CC: :STR: :INDEX: list_end
@@ -3654,9 +3665,15 @@ gotwork
         MOV     R0,#0
         STR     R0,automenu_inactivetimeout
 ;
+        STRB    R0,selecttable_crit     ; don't mind losing it on an invalidate cache service call
+        STRB    R0,tsprite_needsregen   ; doesn't because there isn't one
+
         STR     R0,pixtable_at          ; no pixel translation table
         STR     R0,pixtable_size
-        STRB    R0,preservett           ; don't mind losing it on an invalidate cache service call
+
+        STR     R0,tpixtable_at         ; no tool pixel translation table
+        STR     R0,tpixtable_size
+
         STR     R0,list_at
         STR     R0,list_size            ; mark to indicate now list present
         STR     R0,filehandle
@@ -3669,7 +3686,7 @@ gotwork
         [ NewErrorSystem
         STR     R0,watchdogcodew
         ]
-        ADRL    R14,tools_area
+        ADRL    R14,tool_list_backup
         STR     R0,[R14]
 ;        ADRL    R14,wimpmodebefore
 ;        STR     R0,[R14]
@@ -4306,20 +4323,20 @@ releasewrchvpremodechange
 
 invalidatecache
         Push    "R0,R2,LR"
-        LDRB    R2,preservett           ; avoid discarding the table when we know
+        LDRB    R2,selecttable_crit     ; avoid discarding the table when we know
         CMP     R2,#0                   ; that it is still valid
-        BNE     %FT10
+        Pull    "R0,R2,PC", NE
 
         LDR     R2,pixtable_at
         CMP     R2,#0                   ; has a pixtable been setup?
         MOVNE   R0,#ModHandReason_Free
-        BLNE    XROS_Module              ; attempt to release - ignore errors
-;
+        BLNE    XROS_Module             ; attempt to release - ignore errors
+
         MOV     R2,#0
         STR     R2,pixtable_at          ; mark the pixtable as being zapped!
-;
+
         MOV     R2,#-1                  ; and the PixTrans mode
-        STR     R2,lastmode
+        STR     R2,sprite_lastmode
 
       [ ThreeDPatch
 ; MB - must add invalidating of new tile pixel tables here
@@ -4329,23 +4346,20 @@ invalidatecache
         STR     R2,tile_temptab
       ]
 
-        [ false
-        BL      freetoollist            ; Lose cached tool data
-        |
-; tool translation table is invalid,  try to recache
-        LDR     R2,tool_area
-        CMP     R2,#0
-        BEQ     %FT99
-        LDR     R2,tool_list
-        CMP     R2,#0
-        BEQ     %FT99
+        LDR     R2,tpixtable_at
+        CMP     R2,#0                   ; has a tool pixtable been setup?
+        MOVNE   R0,#ModHandReason_Free
+        BLNE    XROS_Module             ; attempt to release - ignore errors
 
         MOV     R2,#0
-        STR     R2,tool_list      ; force recache next time we need it
+        STR     R2,tpixtable_at         ; mark the tool pixtable as being zapped!
+        STR     R2,tool_transtable
+
+        MOV     R2,#-1                  ; and the tool PixTrans mode
+        STR     R2,tsprite_lastmode
+
+        STRB    R2,tsprite_needsregen   ; re-calcuate border based information
 
-99
-        ]
-10
         Pull    "R0,R2,PC"
 
 ;
@@ -4587,6 +4601,10 @@ deallocateptrs	ROUT
         LDR     R2,pixtable_at
         CMP     R2,#0
         BLNE    XROS_Module              ; release the pixtrans table (ignore errors)
+;
+        LDR     R2,tpixtable_at
+        CMP     R2,#0
+        BLNE    XROS_Module              ; release the tools pixtrans table (ignore errors)
 ;
         LDR     R2,fileaddress
         CMP     R2,#0
@@ -4594,6 +4612,8 @@ deallocateptrs	ROUT
 ;
         STR     R1,pixtable_at
         STR     R1,pixtable_size
+        STR     R1,tpixtable_at
+        STR     R1,tpixtable_size
         STR     R1,filehandle
         STR     R1,fileaddress          ; tag as free'd
 ;
@@ -5384,7 +5404,7 @@ sysinfo_memclaim
         B       ExitWimp
 
 sysinfo_transtables
-        LDR     R0,pixtable_at
+        LDR     R0,tpixtable_at
         ADRL    R2,tool_plotparams
         LDR     R1,[R2]
         STMIA   sp,{R1-R2}
diff --git a/s/Wimp02 b/s/Wimp02
index 1d99d1f59631fca976677f2908b26b2e276e5b1d..b177578f2c1d0bd5d5a43685b25f295a17a93748 100644
--- a/s/Wimp02
+++ b/s/Wimp02
@@ -2965,7 +2965,7 @@ inittasks
         STR     R0,menutaskhandle
 ;
         MOV     R14,#-1         ; invalidate sprite translation stuff
-        STR     R14,lastmode
+        STR     R14,sprite_lastmode
 ;
 ; Braindead panic redraw indication.
 ;
@@ -3320,10 +3320,12 @@ recalcpalette
 ;
         BL      readvduvars             ; just in case
 ;
-        MOV     R14,#-1                 ; sprite stuff is now invalid (as is ColourTrans's cache)
-        STR     R14,lastmode
         SWI     XColourTrans_InvalidateCache
 ;
+      [ false  ; this stuff gets done in Service_InvalidateCache
+        MOV     R14,#-1                 ; sprite stuff is now invalid (as is ColourTrans's cache)
+        STR     R14,sprite_lastmode
+
         LDR     R2,pixtable_at
         TEQ     R2,#0                   ; pixtable currently claimed?
         MOVNE   R0,#ModHandReason_Free
@@ -3331,6 +3333,7 @@ recalcpalette
 ;
         MOV     R2,#0
         STR     R2,pixtable_at          ; mark block as released
+      ]
 ;
 ; first set up border & mouse colours
 ;
@@ -8855,7 +8858,7 @@ forcetint_on EntryS "R0,R2"
         TEQ     R0, #0
         TEQNE   R0, R14
         STRNEB  R0, tinted_tool
-        BLNE    recache_tools_trans2    ; uses R2 as set up above (-> first sprite)
+        BLNE    recache_tools_trans     ; uses R2 as set up above (-> first sprite)
         EXITS                           ; must preserve flags
 
 ;
@@ -8871,7 +8874,7 @@ forcetint_off EntryS "R2"
         TEQ     R14, #0
         MOVNE   R14, #0
         STRNEB  R14, tinted_tool
-        BLNE    recache_tools_trans2    ; uses R2 as set up above (-> first sprite)
+        BLNE    recache_tools_trans     ; uses R2 as set up above (-> first sprite)
         EXITS                           ; must preserve flags
 
       ]
diff --git a/s/Wimp04 b/s/Wimp04
index 76b14fb86e18ebb26326d77d6538e4f017861b4e..892432278413a48ed9617d3e9f65794335fdedc9 100644
--- a/s/Wimp04
+++ b/s/Wimp04
@@ -2080,7 +2080,7 @@ icontext_paint
 
         LDR     R0,tool_list            ; 320nk
         TEQ     R0,#0
-        BLEQ    recache_tools_trans     ; make sure there's something there
+        BLEQ    restore_tool_list       ; make sure there's something there
                                         ; just in case we're in the middle of
                                         ; plotting a title bar, for instance.
 
@@ -2576,7 +2576,7 @@ iconformatted_width_ok
 
         LDR     R0,tool_list            ; 320nk
         TEQ     R0,#0
-        BLEQ    recache_tools_trans     ; make sure there's something there
+        BLEQ    restore_tool_list       ; make sure there's something there
                                         ; just in case we're in the middle of
                                         ; plotting a title bar, for instance.
 iconformatted_fancy_next
@@ -3222,7 +3222,7 @@ SWIWimp_ReadPixTrans
         BVS     ExitWimp
 ;
         CMP     R6,#0
-        ADRNE   R14,factors
+        ADRNE   R14,sprite_factors
         LDMNEIA R14,{R1-R4}
         STMNEIA R6,{R1-R4}              ; copy factors out
 ;
@@ -3234,6 +3234,46 @@ SWIWimp_ReadPixTrans
 ;
         B       ExitWimp
 
+;;----------------------------------------------------------------------------
+;; Rationalise sprite scaling factors
+;; Entry:  R0,R1  sprite's eigx/eigy
+;;         R5,R6  mode's eigx/eigy
+;;         R2 --> where to store the factors
+;; Exit:   R0,R1,R5,R6 corrupted
+;;         [R2]   factors stored (xmul,ymul,xdiv,ydiv)
+;;----------------------------------------------------------------------------
+rationalisefactors
+        Entry
+        MOV     R14,#1
+
+        ; all factors are ?:1 or 1:? so make R0:R5, R1:R6
+        ; into this form
+        CMP     R0,R5
+        MOVEQ   R0,#1
+        MOVEQ   R5,#1
+
+        MOVLT   R5,R14,LSL R5
+        MOVLT   R5,R5, LSR R0
+        MOVLT   R0,#1
+
+        MOVGT   R0,R14,LSL R0
+        MOVGT   R0,R0, LSR R5
+        MOVGT   R5,#1
+
+        CMP     R1,R6
+        MOVEQ   R1,#1
+        MOVEQ   R6,#1
+
+        MOVLT   R6,R14,LSL R6
+        MOVLT   R6,R6, LSR R1
+        MOVLT   R1,#1
+
+        MOVGT   R1,R14,LSL R1
+        MOVGT   R1,R1, LSR R6
+        MOVGT   R6,#1
+
+        STMIA   R2,{R0-R1,R5-R6}       ; store the scaling block
+        EXIT
 
 ;;----------------------------------------------------------------------------
 ;; Mode-independent sprite code
@@ -3244,13 +3284,11 @@ SWIWimp_ReadPixTrans
 ;;         mode data set up if different input mode from last time
 ;;----------------------------------------------------------------------------
 
-        ASSERT  ?pixtable_params =4*6
-
 cachespritedata
         Entry   "R1-R2,R5-R7"
 
         MOV     R2,#1
-        STRB    R2,preservett           ; entering critical period for pixtable
+        STRB    R2,selecttable_crit     ; entering critical period for pixtable
 
         LDR     R2,lengthflags
         CMP     R2,#0                   ; absolute pointer?
@@ -3258,7 +3296,7 @@ cachespritedata
         BLNE    cachespriteaddress
         MOVVC   R0,#&200+SpriteReason_ReadSpriteSize
         SWIVC   XOS_SpriteOp            ; read information about the sprite
-        EXIT    VS
+        BVS     %FT92
 ;
 ; R2 -> sprite in area
 ;
@@ -3271,27 +3309,16 @@ cachespritedata
         CMP     R14,#0                  ; is a pixtable defined?
         BEQ     %FT10
 
-      [ TrueIcon3
-        LDRB    R14, tinted_tool
-        TEQ     R14, #0                 ; if it's tinted, we must recalculate the table
-        BNE     %FT10
-      ]
-
         TEQ     R7,#spPalette           ; does it have a palette?
-        LDREQ   R14,lastmode
+        LDREQ   R14,sprite_lastmode
         TEQEQ   R6,R14                  ; no, so have we already cached this information?
-        EXIT    EQ
+        BEQ     %FT92
 
 10      MOV     R0,R6                   ; R0 = mode of sprite
 
         TEQ     R7,#spPalette
         MOVNE   R6,#-1                  ; if it has a palette then corrupt last mode
-      [ TrueIcon3
-        LDRB    R14, tinted_tool
-        TEQ     R14, #0                 ; if we're generating a tinted table, corrupt last mode too
-        MOVNE   R6, #-1
-      ]
-        STR     R6,lastmode
+        STR     R6,sprite_lastmode
 
         Push    "R2,R3-R4"              ; R2 -> sprite, R3,R4 = height / width
 
@@ -3307,15 +3334,11 @@ cachespritedata
         SWIVC   XOS_ReadModeVariable
         STRVC   R2,sprite_log2py        ; get the Y scaling factor (pixels => OS units)
         Pull    "R2,R3-R4",VS
-        EXIT    VS
+        BVS     %FT92
 
         LDR     R1,sprite_log2bpp
         LDR     R6,log2bpp
         TEQ     R1,R6                   ; any special translating?
-;      [ TrueIcon3
-;        LDRB    R1, tinted_tool
-;        TEQEQ   R1, #0                  ; any special translating due to tinting?
-;      ]
         LDR     R0,sprite_log2px
         LDR     R5,log2px
         TEQEQ   R0,R5
@@ -3324,50 +3347,16 @@ cachespritedata
         TEQEQ   R1,R6                   ; any special scaling?
         MOVEQ   R14,#0
         MOVNE   R14,#-1
-        STR     R14,needsfactors        ; can be modified later
-
-        MOV     R14,#1
-        [ false
-        MOV     R0,R14,LSL R0           ; multiplication factors
-        MOV     R1,R14,LSL R1
-        MOV     R5,R14,LSL R5           ; division factors
-        MOV     R6,R14,LSL R6
-        |
-        ; all factors are ?:1 or 1:? so make R0:R5, R1:R6
-        ; into this form
-        CMP     R0,R5
-        MOVEQ   R0,#1
-        MOVEQ   R5,#1
-
-        MOVLT   R5,R14,LSL R5
-        MOVLT   R5,R5, LSR R0
-        MOVLT   R0,#1
-
-        MOVGT   R0,R14,LSL R0
-        MOVGT   R0,R0, LSR R5
-        MOVGT   R5,#1
-
-        CMP     R1,R6
-        MOVEQ   R1,#1
-        MOVEQ   R6,#1
-
-        MOVLT   R6,R14,LSL R6
-        MOVLT   R6,R6, LSR R1
-        MOVLT   R1,#1
-
-        MOVGT   R1,R14,LSL R1
-        MOVGT   R1,R1, LSR R6
-        MOVGT   R6,#1
-        ]
+        STRB    R14,sprite_needsfactors ; may be modified later
 
-        ADR     R14,factors
-        STMIA   R14,{R0-R1,R5-R6}       ; store the scaling block
+        ADR     r2,sprite_factors
+        BL      rationalisefactors
 
         Pull    "R1"                    ; R1 -> sprite
         MOV     R2,#-1
         MOV     R3,#-1                  ; convert to the current mode
       [ Medusa
-        MOV     R5,#(1:SHL:0) :OR: 1:SHL:1 ; See PRM 5a-120
+        MOV     R5,#(1:SHL:0) :OR: 1:SHL:1 ; Use mode's palette if sprite has none
       |
         MOV     R5,#(1:SHL:0)
       ]
@@ -3388,7 +3377,7 @@ cachespritedata
         BLT     %FT02
 
         LDR     R0,baseofromsprites     ; might have 8+ bpp sprites in ROM now
-        LDR     R4,[R0,#0]
+        LDR     R4,[R0,#saEnd]
         ADD     R4,R0,R4                ; R4 -> end of ROM sprite area
         CMP     R1,R0
         CMPHS   R4,R1                   ; is sprite in ROM?
@@ -3399,23 +3388,6 @@ cachespritedata
 ; it based on the translation table defined in workspace
 ;
 
-        [ false
-; nk
-        LDR     R0,log2bpp
-        TEQ     R0,R14
-        BNE     %FT02
-; same depth, no palette so no trans table
-        LDR     R2,pixtable_at
-        CMP     R2,#0                   ; is there a pixel table defined yet?
-        MOVNE   R0,#ModHandReason_Free
-        BLNE   XROS_Module              ; free it if there is - ignoring errors
-
-        MOV     R2,#0
-        STR     R2,pixtable_at          ; mark as the pix table has been released
-        STR     R2,pixtable_size
-        Pull    "R3,R4"
-        EXIT
-        ]
 02
         LDR     R0,[R1,#spMode]         ; R0 = mode of sprite
         ADRL    R1,temppaltable         ; R1 -> temporary palette area
@@ -3472,22 +3444,13 @@ cachespritedata
 20      MOV     R6,R4                   ; R6 = size of table generated (first time)
         LDR     R4,pixtable_at
 
-        ADR     R7,pixtable_params
-        STMIA   R7,{R0-R1,R2-R3,R4,R5}  ; push enty parameters for the translation
+        ASSERT  ?selecttable_args = 4*6
+        ADR     R7,selecttable_args
+        STMIA   R7,{R0-R1,R2-R3,R4,R5}  ; cache entry parameters for the translation
 
         Debug   ic,"Sprite src mode, src pptr, dest mode, dest pptr",R0,R1,R2,R3
 
-      [ TrueIcon3
-        Push    "R6,R7"
-        LDRB    R6, tinted_tool
-        ORR     R5, R5, R6
-        MOV     R6, wsptr
-        ADRL    R7, tintfunc
-        SWI     XColourTrans_GenerateTable
-        Pull    "R6,R7"
-      |
         SWI     XColourTrans_SelectTable
-      ]
         BVS     %FT90                   ; return if not important
 
         CMP     R6,#256
@@ -3497,16 +3460,17 @@ cachespritedata
         BMI     %FT90                   ; return if end of the world reached
 
         LDRB    R14,[R4,R6]
-        TEQ     R14,R6                  ; is the byte valid?
+        TEQ     R14,R6                  ; colour number = index? (1:1 mapped)
         BEQ     %BT35
 40
         MOV     R14,#-1
-        STR     R14,needsfactors        ; mark as needing translation
+        STRB    R14,sprite_needsfactors ; mark as needing translation
 90
-        MOV     R3, #0
-        STRB    R3, preservett          ; passed the critical moment for pixtable
-
         Pull    "R3-R4"
+92
+        MOV     R14, #0
+        STRB    R14, selecttable_crit   ; passed the critical moment for pixtable
+
         EXIT
 
 ;..............................................................................
@@ -3898,12 +3862,12 @@ wimp_SpriteOp_putsprite
       ]
         BLNE    calcinverse             ; updates R7
 ;
-        LDR     R0,needsfactors
+        LDRB    R0,sprite_needsfactors
         TEQ     R0,#0                   ; do I need to translate
         TSTEQ   R1,#if_halfsize         ; does need factors if half size
 ;
         MOVNE   R0,#SpriteReason_PutSpriteScaled
-        ADRNE   R6,factors
+        ADRNE   R6,sprite_factors
         BNE     scaled
 ;
         MOV     R0,#SpriteReason_PutSpriteUserCoords
@@ -3993,44 +3957,26 @@ calcinverse ROUT
         EXIT    EQ                      ; no pixtable!
       [ true ; BJGA bugfix: was sometimes trying to work from a paged-out sprite!
         LDR     R1, sprite_log2bpp      ; if <256-colour sprite without palette, we pass palette from Wimp workspace, so no problem
-        CMP     R1, #3                  ; if <256-colour sprite with palette, cachespritedata has already updated pixtable_params
+        CMP     R1, #3                  ; if <256-colour sprite with palette, cachespritedata has already updated selecttable_args
         BLGE    cachespriteaddress      ; R2 -> this sprite, ie *not* the first sprite in this run of matching-mode sprites!
         EXIT    VS                      ; bail out now if sprite not found!
         CMP     R1, #3
         Push    "R2", GE
-        ADR     R0, pixtable_params
+        ADR     R0, selecttable_args
         LDMIA   R0, {R0-R5}
         LDRGE   R0, baseofsprites       ; any non-system sprite area will do
         Pull    "R1", GE
       |
-        ADR     R0,pixtable_params
+        ADR     R0,selecttable_args
         LDMIA   R0,{R0-R5}              ; get the parameters for the call
-
-        [ false
-        BNE     %FT05
-        ; pixtable has been stolen! This can make a mess of the tools!!!
-        Push    "R0-R3"
-        MOV     R0,#ModHandReason_Claim
-        LDR     R3,pixtable_size
-        BL      XROS_Module
-        Pull    "R0-R3",VS
-        EXITS   VS                      ; ok as pixtable_at will be zero
-        STR     R2,pixtable_at
-        STR     R2,pixtable_params+16
-        MOV     R4,R2
-        Pull    "R0-R3"
-        STR     R4,[sp,#28]             ; updates R7
-
-05
-        ]
       ]
         ORR     R5,R5,#1:SHL:2          ; mark as a transfer function supplied
         SWI     XColourTrans_GenerateTable
 
 ;        SWI     XColourTrans_InvalidateCache
         MOV     R0,#-1
-        STR     R0,lastmode
-        STR     R0,needsfactors         ; mark as recache and needing translation table
+        STR     R0,sprite_lastmode
+        STRB    R0,sprite_needsfactors  ; mark as recache and needing translation table
 
         CLRV
         EXIT
@@ -4204,101 +4150,6 @@ inversefunc EntryS "R1-R4"
         ORR     R0,R0,R3,LSL #24        ; recombine to make &BBGGRRxx
         EXITS
 
-    [ TrueIcon3
-;------------------------------------------------------------------------------
-; Routine called to process a palette entry to "tint" a tool sprite
-; Maps greys on to title bar foreground-background scale
-; White - &bbbbbb00 - Black   --->   White - [titlecolour] - [truetitlefg]
-;
-; In:   R0 = input palette entry
-; Out:  R0 = modified palette entry
-;       all other registers preserved
-;------------------------------------------------------------------------------
-tintfunc Entry "R1-R8"
-
-        MOV     R8, #&FF
-        MOV     R3, R0, LSR #24         ; blue component
-        AND     R2, R8, R0, LSR #16     ; green component
-        AND     R1, R8, R0, LSR #8      ; red component
-
-        TEQ     R1, R2
-        TEQEQ   R2, R3
-        EXIT    NE                      ; leave colours alone
-
-        LDR     R4, titlecolour
-        AND     R2, R8, R4, LSR #8      ; title background red component
-        AND     R3, R8, R4, LSR #16     ; title background green component
-        MOV     R4, R4, LSR #24         ; title background blue component
-
-        CMP     R1, #&BB
-        BLT     %FT02
-
-        ; bright shades: blend to white
-        SUB     R1, R8, R1              ; distance of source from white
-
-        SUB     R2, R8, R2              ; R2 = distance from white
-        MUL     R0, R1, R2              ; scale up by new size
-        DivRem  R2, R0, #&44, R14       ; scale down by old size
-        SUB     R2, R8, R2              ; make relative to white again
-
-        SUB     R3, R8, R3
-        MUL     R0, R1, R3
-        DivRem  R3, R0, #&44, R14
-        SUB     R3, R8, R3
-
-        SUB     R4, R8, R4
-        MUL     R0, R1, R4
-        DivRem  R4, R0, #&44, R14
-        SUB     R4, R8, R4
-
-        B       %FT01
-
-02      ; dark shades: blend between foreground and background
-        LDR     R7, truetitlefg
-        AND     R5, R8, R7, LSR #8      ; title foreground red component
-        AND     R6, R8, R7, LSR #16     ; title foreground green component
-        MOV     R7, R7, LSR #24         ; title foreground blue component
-
-        RSB     R1, R1, #&BB            ; distance of source from Wimp grey 2
-
-        SUBS    R5, R2, R5              ; R5 = total distance between bg and fg
-        BEQ     %FT10                   ; just in case fg=bg (!)
-        RSBLT   R5, R5, #0              ; R5 = |R5|
-        SavePSR R8                      ; remember flags for later
-        MUL     R0, R1, R5              ; scale up by new size
-        DivRem  R5, R0, #&BB, R14       ; scale down by old size
-        RestPSR R8,,f                   ; restore flags
-        ADDLT   R2, R2, R5              ; make relative to new background
-        SUBGT   R2, R2, R5              ;   (accounting for the sign of R2-R5 above)
-10
-        SUBS    R6, R3, R6
-        BEQ     %FT10
-        RSBLT   R6, R6, #0
-        SavePSR R8
-        MUL     R0, R1, R6
-        DivRem  R6, R0, #&BB, R14
-        RestPSR R8,,f
-        ADDLT   R3, R3, R6
-        SUBGT   R3, R3, R6
-10
-        SUBS    R7, R4, R7
-        BEQ     %FT10
-        RSBLT   R7, R7, #0
-        SavePSR R8
-        MUL     R0, R1, R7
-        DivRem  R7, R0, #&BB, R14
-        RestPSR R8,,f
-        ADDLT   R4, R4, R7
-        SUBGT   R4, R4, R7
-10
-01      ; recombine RGB from R2, R3, R4
-        MOV     R0, R2, LSL #8
-        ORR     R0, R0, R3, LSL #16
-        ORR     R0, R0, R4, LSL #24
-
-        EXIT
-    ]
-
 ;; ---------------------------------------------------------------------------
 ;; Miscellaneous routines
 ;; ---------------------------------------------------------------------------
@@ -6803,18 +6654,23 @@ SWIWimp_SetColourMapping
         CMP     R2,#0                   ; has a pixtable been setup?
         MOVNE   R0,#ModHandReason_Free
         BLNE   XROS_Module              ; attempt to release - ignore errors
-;
+
         MOV     R2,#0
         STR     R2,pixtable_at          ; mark the pixtable as being zapped!
-;
         MOV     R2,#-1                  ; and the PixTrans mode
-        STR     R2,lastmode
+        STR     R2,sprite_lastmode
+;
+        LDR     R2,tpixtable_at
+        CMP     R2,#0                   ; has a tool pixtable been setup?
+        MOVNE   R0,#ModHandReason_Free
+        BLNE   XROS_Module              ; attempt to release - ignore errors
 
-        [ false
-        BL      maketoollist            ; re-calcuate border based information
-        |
-        BL      recache_tools_trans
-        ]
+        MOV     R2,#0
+        STR     R2,tpixtable_at         ; mark the tool pixtable as being zapped!
+        MOV     R2,#-1                  ; and the tool PixTrans mode
+        STR     R2,tsprite_lastmode
+;
+        STRB    R2,tsprite_needsregen   ; re-calcuate border based information
 ;
         LDR     R2,log2bpp              ; is it <8BPP?
         CMP     R2,#3
diff --git a/s/Wimp10 b/s/Wimp10
index d7bc9ddc7fd8b17332295d2e6672737773dfeb31..525506a545c01c11cd713866849ccac5fc154a50 100644
--- a/s/Wimp10
+++ b/s/Wimp10
@@ -634,7 +634,7 @@ maketoollist EntryS "R1-R11"
 ;
         TEQ     R2,#0                   ; has the list buffer been setup yet?
         BNE     %FT07
-        ADRL    R14,tools_area
+        ADRL    R14,tool_list_backup
         LDR     R2,[R14]                ; this is a constant size so try and reuse
         CMP     R2,#0
         STRNE   R2,tool_list
@@ -646,7 +646,7 @@ maketoollist EntryS "R1-R11"
         MOV     R0,#ModHandReason_Claim
         BL      XROS_Module
         STRVC   R2,tool_list
-        ADRVCL  R14,tools_area
+        ADRVCL  R14,tool_list_backup
         STRVC   R2,[R14]
 
         EXITS   VS                      ; return if it fails to claim
@@ -942,25 +942,8 @@ cachetoolspriteaddress ; [spritename], [thisCBptr], [lengthflags] as for cachesp
         MOV     R2,#0
         STR     R2,lengthflags          ; [spritename] is absolute
 ;
-       [ false
-
-        LDR     R2,pixtable_at
-        TEQ     R2,#0
-        LDRNE   R1,tool_transtable
-        TEQNE   R1,R2                   ; if they're the same, don't free
-
-        MOVNE   R0,#ModHandReason_Free
-        BLNE    XROS_Module
-
-        LDR     R2,tool_transtable
-        STR     R2,pixtable_at          ; attempt to reuse area
-        ADRL    R14,tools_trans_size
-        LDR     R2,[R14]
-        STR     R2,pixtable_size
-       |
         BL      freetooltrans           ; release tool translation table
-       ]
-        BL      cachespritedata         ; attempt to build a suitable pixtrans table
+        BL      cachetoolspritedata     ; attempt to build a suitable pixtrans table
 ;
         BVC     %FT42
         ; a failure here usually means that we can't even allocate a pix table
@@ -968,30 +951,35 @@ cachetoolspriteaddress ; [spritename], [thisCBptr], [lengthflags] as for cachesp
         BL      freetoolarea
         EXITS
 42
+      [ Medusa
+        MOV     R1, #8+32               ; Plot masked with wide tables by default
+      |
+        MOV     R1, #8                  ; Plot masked by default
+      ]
       [ fastborders
-        LDR     R1,needsfactors         ; do we need to do translation
-        TEQ     R1,#0
+        LDRB    R0,tsprite_needsfactors ; do we need to do translation
+        TEQ     R0,#0
         LDREQ   R0,=&200+SpriteReason_PutSpriteUserCoords
         LDRNE   R0,=&200+SpriteReason_PutSpriteScaled
-        MOV     R1,#8
         ADRNEL  R2,tool_scalingblk
-        LDRNE   R3,pixtable_at
+        LDRNE   R3,tpixtable_at
         MOVEQ   R3,#0
       |
         LDR     R0,=&200+SpriteReason_PutSpriteScaled
       [ TrueIcon3
-        LDR     R1, tool_area
+        LDR     R14, tool_area
         LDR     R2, ROMstart
         LDR     R3, ROMend
-        CMP     R1, R2
-        CMPHS   R3, R1
-        MOVHS   R1, #0                  ; pretend ROM toolsprites are unmasked
-        MOVLO   R1, #8
+        CMP     R14, R2
+        CMPHS   R3, R14
+      [ Medusa
+        MOVHS   R1, #0+32               ; pretend ROM toolsprites are unmasked
       |
-        MOV     R1,#8
+        MOVHS   R1, #0
+      ]
       ]
         ADRL    R2,tool_scalingblk
-        LDR     R3,pixtable_at
+        LDR     R3,tpixtable_at
       ]
 ;
         ASSERT  tool_maskop = tool_plotop+4
@@ -1005,35 +993,23 @@ cachetoolspriteaddress ; [spritename], [thisCBptr], [lengthflags] as for cachesp
       [ :LNOT: fastborders
         TEQ     R3,#0                   ; not needed with fastborders set
       ]
-        MOVNE   R0,#0
-        STRNE   R0,pixtable_at
-        STRNE   R0,pixtable_size        ; flag as no active pixtable ('cos we stole it!)
-
       [ ChildWindows
-        ADR     R14,factors
+        ADR     R14,tsprite_factors
         LDMIA   R14,{R3,R4,R5,R6}
         ADRL    R14,tool_scalingblk
         STMIA   R14,{R3,R4,R5,R6}        ; take a copy of the scaling block (even if the tools don't always need it)
       |
       [ fastborders
-        ADRNE   R14,factors
+        ADRNE   R14,tsprite_factors
         LDMNEIA R14,{R3,R4,R5,R6}
         STMNEIA R2,{R3,R4,R5,R6}        ; take a copy of the scaling block
       |
-        ADR     R14,factors
+        ADR     R14,tsprite_factors
         LDMIA   R14,{R3,R4,R5,R6}
         STMIA   R2,{R3,R4,R5,R6}        ; take a copy of the scaling block
       ]
       ]
-;
-     [ true
-; we store info about the current pixtable so that we can reuse it without freeing RMA
-; this can become very important as RMA begins to run out.
 
-        LDR     R0,pixtable_size
-        ADRL    R1,tools_trans_size
-        STR     R0,[R1]
-     ]
 ;
 ; calculate values + an OS unit for correct tessalation.
 ;
@@ -1227,20 +1203,21 @@ freetoollist ROUT
 ;;-----------------------------------------------------------------------------
 ;; Free the translation table associated with the tool plotting routines.
 ;;
-;; in   [tool_transtable] -> table / =0 for none
-;; out  [tool_transtable] = 0 (block released)
+;; in   [tpixtable_at] -> table / =0 for none
+;; out  [tpixtable_at] = 0 (block released)
 ;;-----------------------------------------------------------------------------
 
 freetooltrans ROUT
 
         MOV     R1,R14
 ;
-        LDR     R2,tool_transtable
+        LDR     R2,tpixtable_at
         CMP     R2,#0                   ; has a table been defined yet?
         MOVNE   R0,#ModHandReason_Free
         BLNE   XROS_Module              ; if so then release - ignore errors
 ;
         MOV     R0,#0
+        STR     R0,tpixtable_at
         STR     R0,tool_transtable
 ;
         CLRV
@@ -1501,7 +1478,7 @@ modifytool_clicked
         TEQ     R3,#0                   ; is there a glyph list?
         BNE     %FT05
         Push    "R2"                    ; R2 corrupted :-(
-        BL      recache_tools_trans     ; if not, try to get one again
+        BL      restore_tool_list       ; if not, try to get one again
         Pull    "R2"
         LDR     R3,tool_list
         TEQ     R3,#0
@@ -1512,7 +1489,7 @@ modifytool_clicked
       ]
         EXIT    EQ                      ; return 'cos not allowed to toggle the state
 ;
-; scroll bars are a special case - so handle seperatelym
+; scroll bars are a special case - so handle seperately
 ;
       [ PushBothBars
         Pull    "R14"                   ; check to see if an adjust click on a scrollbar
@@ -3030,222 +3007,383 @@ LoseFont_lost_symbol_font
 
       ]
 
-        [       debug
-
-; Some extra tracing routines by Jonathan. All preserve all registers and
-; all flags
-
-; HostFS_WriteC * &40102
+;;-----------------------------------------------------------------------------
+;; Tool_SpriteOp
+;; Perform an OS_SpriteOp on a tool from the tool_area
+;; Entry: R0 reason code (b9 set)
+;;        R2-R7 as required by the respective reason code
+;; Exit:  R0,R1 preserved
+;;        R2-R7 as returned by the respective reason code
+;;-----------------------------------------------------------------------------
 
-;---------------------------------------------------------------------------
-trace_char ROUT
+Tool_SpriteOp
+        EntryS  "R0,R1"
+        LDRB    R1,tsprite_needsregen
+        TEQ     R1,#0
+        BEQ     %FT05
+        Push    "R2"
+        BL      restore_tool_list        ; ensure tool list valid, get 1st sprite entry
+        BL      recache_tools_trans      ; make new tpixtable from 1st sprite entry
+        Pull    "R2"
+        LDR     R7,tool_transtable       ; reload new table
+        MOV     R1,#0
+        STRB    R1,tsprite_needsregen
+05
+        LDR     R1,tool_area             ; R1 is quite often wrong!
+        BIC     R2,R2,#1
+        SWI     XOS_SpriteOp
+        EXITS
 
-; R0 = character to trace
+;;----------------------------------------------------------------------------
+;; Mode-independent sprite code
+;; Entry:  [spritename] --> sprite name
+;;         [thisCBptr] --> sprite area
+;;         [lengthflags] ==> is R2 a name ptr or a sprite ptr?
+;; Exit:   R3,R4 = sprite size (pixels)
+;;         mode data set up if different input mode from last time
+;;----------------------------------------------------------------------------
 
-        EntryS  "R0, R1, R2"
+cachetoolspritedata
+        Entry   "R1-R2,R5-R7"
 
-        CMP     R0, #32
-        BLT     |trace_char: nonprintable character|
-        CMP     R0, #127
-        BGE     |trace_char: nonprintable character|
+        MOV     R2,#1
+        STRB    R2,selecttable_crit     ; entering critical period for pixtable
 
-|trace_char: printable character|
-        ;write character
-        SWI     HostFS_WriteC
-        ;if it's a backslash, write it again
-        CMP     R0, #"\\"
-        SWIEQ   HostFS_WriteC
-        B       |trace_char: exit|
+        LDR     R2,lengthflags
+        CMP     R2,#0                   ; absolute pointer?
+        LDR     R2,spritename
+        BLNE    cachespriteaddress
+        MOVVC   R0,#&200+SpriteReason_ReadSpriteSize
+        SWIVC   XOS_SpriteOp            ; read information about the sprite
+        BVS     %FT92
+;
+; R2 -> sprite in area
+;
+        LDR     R7,[R2,#spImage]
+        LDR     R14,[R2,#spTrans]
+        CMP     R7,R14                  ; min(image,trans)
+        MOVHI   R7,R14
 
-|trace_char: nonprintable character|
-        CMP     R0, #:CHR: 10
-        BNE     |trace_char: control character|
+        LDR     R14,tpixtable_at
+        CMP     R14,#0                  ; is a pixtable defined?
+        BEQ     %FT10
 
-|trace_char: linefeed|
-        SWI     HostFS_WriteC
+      [ TrueIcon3
+        LDRB    R14, tinted_tool
+        TEQ     R14, #0                 ; if it's tinted, we must recalculate the table
+        BNE     %FT10
+      ]
 
-        MOV     R0, #:CHR: 13
-        SWI     HostFS_WriteC
+        TEQ     R7,#spPalette           ; does it have a palette?
+        LDREQ   R14,tsprite_lastmode
+        TEQEQ   R6,R14                  ; no, so have we already cached this information?
+        BEQ     %FT92
 
-        B       |trace_char: exit|
+10      MOV     R0,R6                   ; R0 = mode of sprite
 
-|trace_char: control character|
-        ;save the character
+        TEQ     R7,#spPalette
+        MOVNE   R6,#-1                  ; if it has a palette then corrupt last mode
+      [ TrueIcon3
+        LDRB    R14, tinted_tool
+        TEQ     R14, #0                 ; if we're generating a tinted table, corrupt last mode too
+        MOVNE   R6, #-1
+      ]
+        STR     R6,tsprite_lastmode
 
-        MOV     R1, R0
-        ADR     R2, |trace_char: digits|
+        Push    "R2,R3-R4"              ; R2 -> sprite, R3,R4 = height / width
 
-; R1 = character to trace
-; R2 -> representation table
+        MOV     R1,#VduExt_Log2BPP
+        SWI     XOS_ReadModeVariable
+        STRVC   R2,tsprite_log2bpp      ; get the depth of the sprite
+
+        MOVVC   R1,#VduExt_XEigFactor
+        SWIVC   XOS_ReadModeVariable
+        STRVC   R2,tsprite_log2px       ; get the X scaling factor (pixels => OS units)
+
+        MOVVC   R1,#VduExt_YEigFactor
+        SWIVC   XOS_ReadModeVariable
+        STRVC   R2,tsprite_log2py       ; get the Y scaling factor (pixels => OS units)
+        Pull    "R2,R3-R4",VS
+        BVS     %FT92
+
+        LDR     R1,tsprite_log2bpp
+        LDR     R6,log2bpp
+        TEQ     R1,R6                   ; any special translating?
+        LDR     R0,tsprite_log2px
+        LDR     R5,log2px
+        TEQEQ   R0,R5
+        LDR     R1,tsprite_log2py
+        LDR     R6,log2py
+        TEQEQ   R1,R6                   ; any special scaling?
+        MOVEQ   R14,#0
+        MOVNE   R14,#-1
+        STRB    R14,tsprite_needsfactors       ; may be modified later
+
+        ADR     r2,tsprite_factors
+        BL      rationalisefactors
+
+        Pull    "R1"                    ; R1 -> sprite
+        MOV     R2,#-1
+        MOV     R3,#-1                  ; convert to the current mode
+      [ Medusa
+        MOV     R5,#(1:SHL:0) :OR: 1:SHL:1 :OR: 1:SHL:4 ; Use mode's palette if sprite has none, make wide table
+      |
+        MOV     R5,#(1:SHL:0)
+      ]
+;
+; we must now attempt to cope with the dilemma of sorting out the correct
+; mapping table for the sprite.
+;
+; in earlier versions of the Window Manager it made no attempt to cope
+; with different depth sprites other than 1,2 or 4BPP so we will break
+; new ground and go boldly where no larma has been parping before.
+;
+        LDR     R14,tsprite_log2bpp
 
-        MOV     R0, #"\\"
-        SWI     HostFS_WriteC
+        Debug   ic,"Sprite bpp, palette",R14,R7
 
-        MOV     R0, #"x"
-        SWI     HostFS_WriteC
+        CMP     R14,#3                  ; is it 8,16 or 32BPP?
+        CMPLT   R7,#(spPalette+4)       ; or does it have a palette?
+        BLT     %FT02
 
-        ;trace top nybble
-        MOV     R0, R1, LSR #4
-        LDRB    R0, [R2, R0]
-        SWI     HostFS_WriteC
+        LDR     R0,baseofromsprites     ; might have 8+ bpp sprites in ROM now
+        LDR     R4,[R0,#saEnd]
+        ADD     R4,R0,R4                ; R4 -> end of ROM sprite area
+        CMP     R1,R0
+        CMPHS   R4,R1                   ; is sprite in ROM?
+        LDRLO   R0,baseofsprites        ; no, use RAM sprite area      ; 320nk Medusa fix
+        B       %FT10
+;
+; sprite is in a depth less than 8BPP so take the current palette and munge
+; it based on the translation table defined in workspace
+;
 
-        ;trace bottom nybble
-        AND     R0, R1, #&F
-        LDRB    R0, [R2, R0]
-        SWI     HostFS_WriteC
+02
+        LDR     R0,[R1,#spMode]         ; R0 = mode of sprite
+        ADRL    R1,temppaltable         ; R1 -> temporary palette area
+        Push    "R0-R3,R5"
 
-|trace_char: exit|
-        EXITS
+        BL      getpalpointer           ; R14 -> palette to be used
 
-|trace_char: digits|
-        =     "0123456789ABCDEF"
-        ALIGN
-;---------------------------------------------------------------------------
-trace_string ROUT
+        LDR     R4,tsprite_log2bpp
+        CMP     R4,#1
+        ADRLTL  R4,transtable1          ; R4 => translation 1BPP
+        ADREQL  R4,transtable2          ;       translation 2BPP
+        ADRGTL  R4,transtable4          ;       translation 4BPP
+        MOV     R5,#15
+
+05      LDRB    R3,[R4,R5]              ; get index into real palette
+        LDR     R3,[R14,R3,LSL #2]
+        BIC     R3,R3,#&000000FF        ; R3 = &BBGGRR00
+        STR     R3,[R1,R5,LSL #2]
+        SUBS    R5,R5,#1
+        BPL     %BT05                   ; loop back copying the data
+
+        Pull    "R0-R3,R5"
+
+10      MOV     R4,#0                   ; R4 =0 read table size
+        SWI     XColourTrans_SelectTable
+        BVS     %FT90                   ; exit
+
+        LDR     R14,tpixtable_at
+        TEQ     R14,#0                  ; does the pixtable exist?
+        LDRNE   R14,tpixtable_size
+        CMP     R14,R4                  ; is it big enough?
+        BHS     %FT20
+
+        Push    "R0-R3"
+
+        LDR     R2,tpixtable_at
+        CMP     R2,#0                   ; is there a pixel table defined yet?
+        MOVNE   R0,#ModHandReason_Free
+        BLNE    XROS_Module              ; free it if there is - ignoring errors
 
-; R0 -> string to trace
+        MOV     R2,#0
+        STR     R2,tpixtable_size
+        STR     R2,tpixtable_at         ; mark as the pix table has been released
 
-        EntryS  "R0, R1"
+        MOV     R0,#ModHandReason_Claim
+        MOV     R3,R4
+        BL      XROS_Module              ; attempt to claim a new buffer big enough
+        STRVC   R2,tpixtable_at
+        STRVC   R3,tpixtable_size       ; store pointer and define the size
 
-        MOV     R1, R0
-; R1 -> string to trace
+        STRVS   R0,[SP]
+        Pull    "R0-R3"
+        BVS     %FT90                   ; return if it errors
 
-        B       |trace_string: end loop|
-|trace_string: start loop|
-        BL      trace_char
-        ADD     R1, R1, #1
-|trace_string: end loop|
-        LDRB    R0, [R1]
-        CMP     R0, #:CHR: 0
-        BNE     |trace_string: start loop|
+20      MOV     R6,R4                   ; R6 = size of table generated (first time)
+        LDR     R4,tpixtable_at
 
-        EXITS
-;---------------------------------------------------------------------------
-trace_decimal ROUT
+        Debug   ic,"Sprite src mode, src pptr, dest mode, dest pptr",R0,R1,R2,R3
 
-; R0 = integer to trace
+      [ TrueIcon3
+        Push    "R6,R7"
+        LDRB    R6, tinted_tool
+        ORR     R5, R5, R6
+        MOV     R6, wsptr
+        ADR     R7, tintfunc
+        SWI     XColourTrans_GenerateTable
+        Pull    "R6,R7"
+      |
+        SWI     XColourTrans_SelectTable
+      ]
+        BVS     %FT90                   ; return if not important
 
-        EntryS  "R0, R1, R2"
+        CMP     R6,#256
+        BHI     %FT40                   ; if its greater than 8bpp then we can ignore it (was GT)
 
-        SUB     SP, SP, #16
-        MOV     R1, SP
-        MOV     R2, #15
-        SWI     OS_ConvertInteger4
+35      SUBS    R6,R6,#1                ; decrease the index into the table
+        BMI     %FT90                   ; return if end of the world reached
 
-        ;trace it
-        BL      trace_string
-        ADD     SP, SP, #16
+        LDRB    R14,[R4,R6]
+        TEQ     R14,R6                  ; colour number = index? (1:1 mapped)
+        BEQ     %BT35
+40
+        MOV     R14,#-1
+        STRB    R14,tsprite_needsfactors; mark as needing translation
+90
+        Pull    "R3-R4"
+92
+        MOV     R14, #0
+        STRB    R14, selecttable_crit   ; passed the critical moment for pixtable
 
         EXIT
-;---------------------------------------------------------------------------
-trace_hex ROUT
-
-; R0 = integer to trace
-
-        Push    "R0, R1, R2, LR"
-
-        SUB     SP, SP, #16
-        MOV     R1, SP
-        MOV     R2, #15
-        SWI     OS_ConvertHex8
-
-        ;trace it
-        BL      trace_string
-        ADD     SP, SP, #16
-
-        Pull    "R0, R1, R2, PC",, ^
-;---------------------------------------------------------------------------
-trace_nl ROUT
-
-        EntryS  "R0"
-
-        MOV     R0, #:CHR: 10
-        BL      trace_char
 
-        EXITS
-
-        ]
-
-Tool_SpriteOp
-        EntryS  "R0,R1"
-      [ false ; fastborders
-; This reason code is only generated when fastborders is active - but this comparison
-; is flawed anyway, because bit 9 of R0 is always set at this stage!!  BJGA May 1998
-        TEQ     R0,#SpriteReason_PutSpriteUserCoords
-        BEQ     %FT05                    ; no trans table needed if plotting
-      ]
-        LDR     R1,tool_list
-        TEQ     R1,#0
-        BLEQ    recache_tools_trans
-05
-        LDR     R1,tool_area             ; R1 is quite often wrong!
-        BIC     R2,R2,#1
+    [ TrueIcon3
+;------------------------------------------------------------------------------
+; Routine called to process a palette entry to "tint" a tool sprite
+; Maps greys on to title bar foreground-background scale
+; White - &bbbbbb00 - Black   --->   White - [titlecolour] - [truetitlefg]
+;
+; In:   R0 = input palette entry
+; Out:  R0 = modified palette entry
+;       all other registers preserved
+;------------------------------------------------------------------------------
+tintfunc Entry "R1-R8"
+
+        MOV     R8, #&FF
+        MOV     R3, R0, LSR #24         ; blue component
+        AND     R2, R8, R0, LSR #16     ; green component
+        AND     R1, R8, R0, LSR #8      ; red component
+
+        TEQ     R1, R2
+        TEQEQ   R2, R3
+        EXIT    NE                      ; leave colours alone
+
+        LDR     R4, titlecolour
+        AND     R2, R8, R4, LSR #8      ; title background red component
+        AND     R3, R8, R4, LSR #16     ; title background green component
+        MOV     R4, R4, LSR #24         ; title background blue component
+
+        CMP     R1, #&BB
+        BLT     %FT02
+
+        ; bright shades: blend to white
+        SUB     R1, R8, R1              ; distance of source from white
+
+        SUB     R2, R8, R2              ; R2 = distance from white
+        MUL     R0, R1, R2              ; scale up by new size
+        DivRem  R2, R0, #&44, R14       ; scale down by old size
+        SUB     R2, R8, R2              ; make relative to white again
+
+        SUB     R3, R8, R3
+        MUL     R0, R1, R3
+        DivRem  R3, R0, #&44, R14
+        SUB     R3, R8, R3
+
+        SUB     R4, R8, R4
+        MUL     R0, R1, R4
+        DivRem  R4, R0, #&44, R14
+        SUB     R4, R8, R4
+
+        B       %FT01
+
+02      ; dark shades: blend between foreground and background
+        LDR     R7, truetitlefg
+        AND     R5, R8, R7, LSR #8      ; title foreground red component
+        AND     R6, R8, R7, LSR #16     ; title foreground green component
+        MOV     R7, R7, LSR #24         ; title foreground blue component
+
+        RSB     R1, R1, #&BB            ; distance of source from Wimp grey 2
+
+        SUBS    R5, R2, R5              ; R5 = total distance between bg and fg
+        BEQ     %FT10                   ; just in case fg=bg (!)
+        RSBLT   R5, R5, #0              ; R5 = |R5|
+        SavePSR R8                      ; remember flags for later
+        MUL     R0, R1, R5              ; scale up by new size
+        DivRem  R5, R0, #&BB, R14       ; scale down by old size
+        RestPSR R8,,f                   ; restore flags
+        ADDLT   R2, R2, R5              ; make relative to new background
+        SUBGT   R2, R2, R5              ;   (accounting for the sign of R2-R5 above)
+10
+        SUBS    R6, R3, R6
+        BEQ     %FT10
+        RSBLT   R6, R6, #0
+        SavePSR R8
+        MUL     R0, R1, R6
+        DivRem  R6, R0, #&BB, R14
+        RestPSR R8,,f
+        ADDLT   R3, R3, R6
+        SUBGT   R3, R3, R6
+10
+        SUBS    R7, R4, R7
+        BEQ     %FT10
+        RSBLT   R7, R7, #0
+        SavePSR R8
+        MUL     R0, R1, R7
+        DivRem  R7, R0, #&BB, R14
+        RestPSR R8,,f
+        ADDLT   R4, R4, R7
+        SUBGT   R4, R4, R7
+10
+01      ; recombine RGB from R2, R3, R4
+        MOV     R0, R2, LSL #8
+        ORR     R0, R0, R3, LSL #16
+        ORR     R0, R0, R4, LSL #24
 
-        SWI     XOS_SpriteOp
-        LDR     R1,tool_list             ; if the tool list is wrong then reset the pointer
-        TEQ     R1,#0
-        ADREQL  R1,tools_area
-        LDREQ   R1,[R1]
-        STREQ   R1,tool_list
-        EXITS
+        EXIT
+    ]
 
+;;-----------------------------------------------------------------------------
+;; restore_tool_list
+;; Get a valid tool list from the backup (which is never freed to save bashing the RMA)
+;; Entry: -
+;; Exit:  R2 -> first sprite in the tools list
+;;-----------------------------------------------------------------------------
 
-recache_tools_trans
-        Push    "lr"
-        ADRL    R2,tools_area
+restore_tool_list
+        ADRL    R2,tool_list_backup
         LDR     R2,[R2]                 ; tool list pointer
         STR     R2,tool_list
         LDR     R2,[R2]                 ; get first tool, we assume that this is representitive
-        TEQ     R2,#0
-        BEQ     %FT99
-
-        B       %FT99
-
-99
-        CLRV                            ; clear errors
-        Pull    "PC"
+        MOV     PC, LR
 
  [ TrueIcon3
-; In: R2 -> tool_list
-; note that this code seems once to have been part of recache_tools_trans, but was dead
-; code until the direct_tools_trans2 label was added as part of the TrueIcon3 work
-recache_tools_trans2
-        Push    "R0-R5,R14"
+;;-----------------------------------------------------------------------------
+;; recache_tools_trans
+;; Regenerate the pixel translation tables for the tool sprites
+;; In: R2 -> sprite representative of one in the tool_list
+;;-----------------------------------------------------------------------------
+
+recache_tools_trans
+        Push    "R0-R4,R14"
 
         BIC     R2,R2,#1
         STR     R2,spritename
         MOV     R2,#0
-        STR     R2,lengthflags
-
-        ; if pixtable is already in use, we must free it up before we re-use all
-        ; the the standard pixtable variables in order to invoke cachespritedata
-        LDR     R2,pixtable_at
-        CMP     R2,#0
-        MOVNE   R0,#ModHandReason_Free
-        BLNE    XROS_Module
-
-        LDR     R2,tool_transtable      ; reuse tool_transtable memory area
-        STR     R2,pixtable_at
+        STR     R2,lengthflags          ; flag it's a sprite address (not a name)
 
         MOV     R14,#0
-        STR     R14,tool_transtable     ; for safety, make sure that only one variable points to it at once
+        STR     R14,tool_transtable     ; might move during cachetoolspritedata so kill it
 
-        ADRL    R5,tools_trans_size
-        LDR     R2,[R5]
-        STR     R2,pixtable_size
-        BL      cachespritedata         ; this sets up pixtable area
-        BVS     %FT98
+        BL      cachetoolspritedata     ; this sets up the tool pixtable area
+
+        LDRVC   R0,tpixtable_at
+        STRVC   R0,tool_transtable      ; update the new table location
 
-        LDR     R0,pixtable_size
-        STR     R0,[R5]
-        LDR     R0,pixtable_at
-        STR     R0,tool_transtable
-        MOV     R0,#0
-        STR     R0,pixtable_at          ; exit with standard pixtable marked as needing recalculation
-        STR     R0,pixtable_size
-98
         CLRV                            ; clear errors
-        Pull    "R0-R5,PC"
+        Pull    "R0-R4,PC"
  ]
 
         LTORG