; Copyright 1996 Acorn Computers 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.
;
; s.Backdrop
;
; Handles backdrop window and sprite.




      [ defaultbackdrop
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; CheckLCD
;
; If supporting an LCD use a patterned default backdrop which shimmers less
;
CheckLCD
        Push    "r0-r3,lr"

        LDR     r0,backdrop_options
        TST     r0,#bd_OptionActive    ; do nothing if there is already a backdrop
        Pull    "r0-r3,pc",NE

        MOV     r0,#1
        SWI     XOS_ReadSysInfo
        CMP     r1,#5                   ; check for LCD
        Pull    "r0-r3,pc",NE

        ADR     r2,LCDbackdroptile      ; allocate memory for file name (so *Backdrop works)
        BL      strlen
        MOV     r0,#ModHandReason_Claim
        SWI     XOS_Module
        Pull    "r0-r3,pc",VS

        STR     r2,backdrop_path        ; copy path name
        MOV     r1,r2
        ADR     r0,LCDbackdroptile
        BL      Copy_r0r1

        MOV     r0,#bd_OptionTiled :OR: bd_OptionRecache
        STR     r0,backdrop_options

        LDR     r0,poll_word
        ORR     r0,r0,#PollWordReason_Recache
        STR     r0,poll_word

        Pull    "r0-r3,pc"

LCDbackdroptile
        DCB     "Pinboard:LCDTile",0
        ALIGN
      ]

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; MakeCompactModeWord
;
; Formulate a word that expresses bpp, eigen, palette all in one
;
; Out : r0 = compact word
;       r2 = sprite mode descriptor

MakeCompactModeWord
        Push    "r1, lr"
        MOV     r0, #OsByte_CursorCharacterAndMode
        SWI     XOS_Byte
        Pull    "r1, pc",VS

        CMP     r2, #256                ; Old style mode number limit
        MOVCC   r0, r2                  ; Numbered modes are unique
        Pull    "r1, pc",CC

        SUB     sp, sp, #20*4

        MOV     r1, sp
        SWI     XWimp_ReadPalette
        MOV     r0, #0                  ; Checksum
        MOV     r14, #20                ; Index
10
        SUBS    r14, r14, #1
        LDRB    r1, [sp, r14, LSL #2]
        ADD     r0, r0, r1
        BNE     %BT10

        ADD     sp, sp, #20*4

        ; Mix into &Fxybcccc
        LDRB    r14, [r2, #12]          ; Pixel depth
        ORR     r0, r0, r14, LSL #16
        LDRB    r14, YEig
        ORR     r0, r0, r14, LSL #20
        LDRB    r14, XEig
        ORR     r0, r0, r14, LSL #24
        ORR     r0, r0, #&F0000000      ; Make sure a 1bpp EX0 EY0 mode can't be mistaken
                                        ; for old style mode 0
        CLRV
        Pull    "r1, pc"

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; [Int_]ModeChange
;
; The mode has changed, recalculate bounds and tiles
;

Int_ModeChange
        Push    "lr"
ModeChange

        Debug   bd,"Mode Change"

        [ truncate_filenames
        BL      read_font_widths
        ]

        BL      read_mode_variables
        LDR     r0,backdrop_handle
        STR     r0,[r1],#4
        ADR     r2,bounding_box
        LDMIA   r2,{r2,r3,r4,r5}
        ADD     r4,r4,#100
        ADD     r5,r5,#100
        STMIA   r1,{r2,r3,r4,r5}
        SWI     XWimp_SetExtent
        Pull    "PC",VS

        Debug   bd,"Extent set."

        BL      set_icon_bar_height
      [ useECFforLCD
        BL      setupECF
      ]

; new extent set, now open the window.

        ADR     r1,dataarea
        LDR     r0,icon_bar_height
        STR     r0 ,[r1,#8]             ; Don't cover icon bar
        MOV     r6,#-2
        ADD     r0,r1,#20
        STMIA   r0,{r4,r5,r6}
        SWI     XWimp_OpenWindow
        Pull    "PC",VS
        Debug   bd,"Opened window"

        MOV     r0,#-1                  ; Current mode

        MOV     r1,#VduExt_XWindLimit
        SWI     XOS_ReadModeVariable
        MOVVC   r3,r2
        MOVVC   r1,#VduExt_XEigFactor
        SWIVC   XOS_ReadModeVariable
        MOVVC   r3,r3,ASL r2
        STRVC   r3,Screen_x1
        STRVC   r2,XEig

        MOVVC   r1,#VduExt_YWindLimit
        SWIVC   XOS_ReadModeVariable
        MOVVC   r3,r2
        MOVVC   r1,#VduExt_YEigFactor
        SWIVC   XOS_ReadModeVariable
        MOVVC   r3,r3,ASL r2
        STRVC   r3,Screen_y1
        STRVC   r2,YEig

        Pull    "PC",VS

        LDR     r0,backdrop_options
        TST     r0,#bd_OptionActive
      [ defaultbackdrop
        BNE     %FT01
        BL      CheckLCD                ; if no backdrop then check for LCD
        Pull    "PC"
01
      ]

        TSTNE   r0,#bd_OptionRecache
        Pull    "PC",EQ

        TST     r0, #bd_OptionJPEG
        BNE     %FT03
02
        BL      MakeCompactModeWord
        LDR     r14, CachedBackdropMode
        TEQ     r0, r14

        DebugIf NE, bd,"BackdropMode changed",r0,r14

        LDREQ   r0, CachedBackdrop_x1
        LDREQ   r14, Screen_x1
        TEQEQ   r0, r14
        LDREQ   r0, CachedBackdrop_y1
        LDREQ   r14, Screen_y1
        TEQEQ   r0, r14

        DebugIf NE, bd,"Backdrop mode changed, recacheing sprite"
03
        BLNE    CacheBackdropSprite
        Pull    "PC"

FontChanged
        [ truncate_filenames
        BL      read_font_widths
        ]
        LDR     R0,backdrop_handle
        [ {FALSE}
        SUB     R0,R0,#1
        LDR     R0,[R0,#168]                    ; num icons, NUM_ICONS
        |
        SUB     SP,SP,#128
        Push    "R0"
        MOV     R1,SP
        ORR     R1,R1,#1                       ; don't want icons
        SWI     XWimp_GetWindowInfo
        LDR     R0,[SP,#88]
        ADD     SP,SP,#132
        ]
        MOV     R1,#0
        STR     R0,All_PB_Icons
        TEQ     R0,R1
        Pull    "PC",EQ
fontchanged_loop
        LDR     R0,backdrop_handle
        SUB     SP,SP,#32
        Push    "R0,R1"
        MOV     R1,SP
        SWI     XWimp_GetIconState
        BVS     fontchanged_end
        LDR     R0,[sp,#24]             ; flags
        ADD     R1,sp,#28               ; text
        TST     R0,#if_text
        BEQ     fontchanged_next
        TST     R0,#if_indirected
        LDRNE   R1,[R1]
        MOV     R0,#1
        MOVNE   R2,#0
        MOVEQ   R2,#12
        SWI     XWimp_TextOp
        ADD     R14,sp,#8
        LDMIA   R14,{R2-R5}
        SUB     R14,R4,R2
        CMP     R14,R0
        ADDLT   R4,R2,R0                ; x1 = x0+width
        LDMIA   sp,{R0-R1}              ; not ! (!)
        SWI     XWimp_ResizeIcon
        BVS     fontchanged_end
fontchanged_next
        ADD     SP,SP,#40
        ADD     R1,R1,#1
        LDR     R0,All_PB_Icons
        TEQ     R0,R1
        Pull    "PC",EQ
        B       fontchanged_loop
fontchanged_end
        ADD     SP,SP,#40
        CLRV
        Pull    "PC"

      [ :LNOT: ursulawimp               ; No palette utility
PaletteChange

        Debug   bd,"Palette change"

        LDR     r0,backdrop_options
        TST     r0,#bd_OptionActive
        TSTNE   r0,#bd_OptionRecache
        Pull    "PC",EQ

        BL      CacheBackdropSprite

        Pull    "PC"
      ]


;---------------------------------------------------------------
; CacheBackdropSprite
;
; Cache backdrop sprite for current mode
;
; In :
;       [backdrop_path]  name of sprite file.
;
; Out:
;       Sprite cached for current mode.
;
; This must always be entered when we are the current task !

CacheBackdropSprite     ROUT
        Push    "LR"

        LDR     r0,backdrop_path
        CMP     r0,#0

 [ technicolour_text
        BGT     %FT01
        LDR     r0,backdrop_handle
        MOV     r1,#0
        MOV     r2,#0
        MOV     r3,#&8000
        MOV     r4,#&8000
        SWI     XWimp_ForceRedraw
        Pull    "PC"
01
 |
        Pull    "PC",LE
 ]

        SWI     XHourglass_On
        BL      Int_CacheBackdropSprite
        BVS     %FT01

      [ debugspr
        MOV     r0,#&20C
        MOV     r1,#&8000
        ADR     r2,savedspritepath
        SWI     XOS_SpriteOp
        B       %FT20
savedspritepath DCB     "scsi::4.$.tmp.sprites.pbsaved"
        ALIGN
20
      ]

        SWI     XHourglass_Off
        LDR     r0,backdrop_handle
        MOV     r1,#0
        MOV     r2,#0
        MOV     r3,#&8000
        MOV     r4,#&8000
        SWI     XWimp_ForceRedraw

        LDRVC   r0,backdrop_options
        ORRVC   r0,r0,#bd_OptionActive
        STRVC   r0,backdrop_options
        Pull    "PC",VC

01
        Push    "r0"                    ; If failed, free any used memory,
        SWI     XHourglass_Off
        MOV     r0,#0                   ; and mark as inactive.
        MOV     r1,#-1
        SWI     XWimp_SlotSize
        LDR     r0,backdrop_options
        BIC     r0,r0,#bd_OptionActive
        STR     r0,backdrop_options
        Pull    "r0"
        SETV
        Pull    "PC"


Int_CacheBackdropSprite ROUT

        Push    "LR"

; First check that the file still exists and is still a sprite file.


        MOV     r0,#OSFile_ReadWithTypeNoPath
        LDR     r1,backdrop_path
        SWI     XOS_File
        Pull    "PC",VS

        CMP     r0,#1
        MOVNE   r2,r0
        MOVNE   r0,#OSFile_MakeError
        SWINE   XOS_File
        Pull    "PC",VS

        ADD     r4,r4,#4
        STR     r4,file_size

        ; JPEG backdrop support
        LDR     r14,=&C85
        CMP     r6,r14
        BNE     %FT01
        BL      Int_CacheJPEG
        Pull    "PC"
01

        LDR     r14,=&FF9
        CMP     r6,r14
        ADRNEL  r0,ErrorBlock_Pinboard_NotASprite
        LDRNE   r4,backdrop_path
        BLNE    msgtrans_errorlookup
        Pull    "PC",VS

; It still exists !

; See how much memory we need to store it ...

        LDR     r0,backdrop_options
        BIC     r0, r0, #bd_OptionJPEG
        STR     r0, backdrop_options

        TST     r0,#bd_OptionScaled             ; Scaled ?
        BEQ     %FT01

; Sprite is scaled, get screen size (r4 = width, r5 = height)

        MOV     r0,#-1                          ; Use current mode

        MOV     r1,#VduExt_XWindLimit           ; Screen width in pixels
        SWI     XOS_ReadModeVariable
        ADDVC   r4,r2,#1
        STRVC   r4,scale_x1
        MOVVC   r1,#VduExt_YWindLimit           ; Screen height in pixels
        SWIVC   XOS_ReadModeVariable
        ADDVC   r5,r2,#1
        STRVC   r5,scale_y1
        Pull    "PC",VS

        B       %FT10                           ; Go allocate memory etc.

01

; We are not going to scale it so find out how big it will be in the current mode.

        MOV     r0,#open_read :OR: open_nopath :OR: open_mustopen :OR: open_nodir
        LDR     r1,backdrop_path
        SWI     XOS_Find                        ; Open for reading.
        Pull    "PC",VS

        MOV     r1,r0
        MOV     r0,#OSGBPB_ReadFromGiven        ; Read bytes from file
        ADR     r2,dataarea
        MOV     r3,#?saFirst
        MOV     r4,#saFirst - 4                 ; Sprite files are sprite areas with saEnd missing
        SWI     XOS_GBPB
        BVS     %FT05

        LDR     r0,dataarea
        SUB     r4,r0,#4
        Debug   bd,"Offset to sprite is ",r4
        MOV     r0,#OSGBPB_ReadFromGiven
        ADR     r2,dataarea
        MOV     r3,#SpriteCBsize
        SWI     XOS_GBPB                        ; Read sprite header
        BVC     %FT06
05
        Push    "r0"                            ; Preserve original error
        MOV     r0,#0
        SWI     XOS_Find
        ADDVS   sp,sp,#4
        Pull    "r0",VC
        SETV
        Pull    "PC"

        LTORG

06
        MOV     r0,#0
        SWI     XOS_Find

        ADR     r2,dataarea
        LDR     r0,[r2,#spMode]
        Debug   bd,"Sprite mode is ",r0

        LDR     r5,[r2,#spHeight]               ; Get height of sprite
        ADD     r5,r5,#1
        Debug   bd,"Sprite height is ",r5

        LDR     r4,[r2,#spWidth]                ; Get width in words
        MOV     r4,r4,LSL #5                    ; Max width in bits
        LDR     r3,[r2,#spRBit]                 ; Get last bit used
        Debug   bd,"Last bit = ",r3
        ADD     r4,r4,r3                        ; Adjust width
        LDR     r3,[r2,#spLBit]                 ; Get first bit used
        Debug   bd,"First bit = ",r3
        SUB     r4,r4,r3                        ; Adjust width
        ADD     r4,r4,#1                        ; Real width in bits
        MOV     r1,#VduExt_Log2BPP              ; get log2bpp for sprites mode
        SWI     XOS_ReadModeVariable
        Pull    "PC",VS
        MOV     r4,r4,LSR r2                    ; width in pixels
        Debug   bd,"Sprite width is ",r4

        MOV     r1,#VduExt_YEigFactor           ; Get YEig for sprite's mode
        SWI     XOS_ReadModeVariable
        Pull    "PC",VS
        MOV     r5,r5, ASL r2           ; Height in OS units in sprites mode

        MOV     r1,#VduExt_XEigFactor   ; Get XEig for sprite's mode
        SWI     XOS_ReadModeVariable
        Pull    "PC",VS
        MOV     r4,r4, ASL r2           ; Width in OS units in sprites mode

        ; Now convert back to pixels for current mode
        LDR     r2, YEig
        MOVS    r5,r5, LSR r2           ; Height in pixels
        MOVEQ   r5,#1                   ; Must be minimum of 1 pixel
        MOV     r2,r5, LSL r2           ; Height in OS units in current mode
        STR     r2,scale_y1
        Debug   bd,"Height in OS units is ",r2

        LDR     r2, XEig
        MOVS    r4,r4, LSR r2           ; Width in pixels
        MOVEQ   r4,#1                   ; Must be minimum of 1 pixel
        MOV     r2,r4, LSL r2           ; Width in OS units in current mode
        STR     r2,scale_x1
        Debug   bd,"Width in OS units is ",r4

10
        MOV     r0,#-1
        MOV     r1,#VduExt_Log2BPP
        SWI     XOS_ReadModeVariable    ; Get Log2BPP for current mode

        MOV     r3,r4,ASL r2            ; Width in bits
        ADD     r3,r3,#7
        MOV     r3,r3,LSR #3            ; Width in bytes
        ADD     r3,r3,#3
        BIC     r3,r3,#3                ; rounded up to nearest word

        MUL     r2,r3,r5                ; r2 = size in bytes

        Debug   bd,"Destination sprite width = ",r4
        Debug   bd,"Destination sprite height = ",r5
        Debug   bd,"Sprite size would be ",r2

        ADD     r2,r2,#&100
        STR     r2,slot_size            ; Amount for actual sprite.

; Now get size of sprite in file

        LDR     r0,file_size
        ADD     r2,r2,r0
        STR     r2,tmp_slot_size

; Now get the memory we need.

        MOV     r3,r2
        MOV     r0,r2
        MOV     r1,#-1
        Debug   bd,"Slot size required is ",r0
        SWI     XWimp_SlotSize
        MOVVS   r0,#0
        Debug   bd,"actual Slot size is ",r0

        CMP     r3,r0
        BLS     got_memory

        LDR     r0,backdrop_handle
        MOV     r1,#0
        MOV     r2,#0
        MOV     r3,#&8000
        MOV     r4,#&8000
        SWI     XWimp_ForceRedraw

        ADRL    r0,ErrorBlock_Pinboard_NoRoom
        BL      msgtrans_errorlookup    ; V set on exit

        Pull    "PC"

got_memory

        Debug   bd,"Got memory, loading file"

        LDR     r14,backdrop_options
        ORR     r14,r14,#bd_OptionActive
        STR     r14,backdrop_options

        ; mark as active to stop memory from being stolen!

        MOV     r0,#OSFile_LoadNoPath
        LDR     r1,backdrop_path
        MOV     r2,#&8000
        LDR     r3,slot_size
        ADD     r2,r2,r3        ; Address to load file.
        LDR     r14,file_size
        STR     r14,[r2],#4
        Push    "r2,r4,r5"
        MOV     r3,#0           ; Load at given address
        SWI     XOS_File
        Pull    "r2,r4,r5"

        [ {FALSE}
        LDRVS   r14,backdrop_options
        BICVS   r14,r14,#bd_OptionActive
        STRVS   r14,backdrop_options
        ]

        BVC     LoadedOK

        Push    R0
        LDR     r0,backdrop_handle
        MOV     r1,#0
        MOV     r2,#0
        MOV     r3,#&8000
        MOV     r4,#&8000
        SWI     XWimp_ForceRedraw

        Pull    R0
        SETV

        Pull    "PC"

LoadedOK

        Debug   bd,"File loaded."

        SUB     r1,r2,#4        ; Pointer to sprite area
        LDR     r2,[r1,#8]
        ADD     r2,r2,r1        ; Pointer to sprite
        Push    "r1,r2"

        MOV     r1,#&8000
        LDR     r2,slot_size
        STR     r2,[r1]
        MOV     r2,#&10
        STR     r2,[r1,#8]
        LDR     r0,=&100 + SpriteReason_ClearSprites
        SWI     XOS_SpriteOp

        Debug   bd,"Sprite area initialised"

        BLVC    MakeCompactModeWord
        ADDVS   sp,sp,#8
        Pull    "PC",VS

        MOV     r6, r2                  ; For SpriteReason_CreateSprite
        STR     r0,CachedBackdropMode

        Debug   bd,"BackdropMode is brought to you by the number ",r0

        LDR     r0,Screen_x1
        LDR     r1,Screen_y1
        STR     r0,CachedBackdrop_x1
        STR     r1,CachedBackdrop_y1

        LDR     r0,=&100 + SpriteReason_CreateSprite
        MOV     r1,#&8000
        ADRL    r2,BackdropSpriteName   ; Create new sprite in current mode
        MOV     r3,#0                   ; No palette

        Debug   bd,"Xsize Ysize",r4,r5
        SWI     XOS_SpriteOp
        ADDVS   sp,sp,#8
        Pull    "PC",VS
        Debug   bd,"Created new sprite X x Y",r4,r5

; Now plot old sprite into new one:

        Pull    "r1,r2"                 ; Get old sprite pointer and area
        MOV     r9,r1
        MOV     r10,r2

        LDR     R0,[R2,#spImage]
        LDR     LR,[R2,#spTrans]
        CMP     R0,R2
        MOVGT   R0,LR                   ; min(spImage,spMask) = offset to sprite data
        CMP     R0,#spPalette           ; does the sprite have a palette?
        BGT     %FT01                   ; Yup - so decode it properly

        Push    "R2"
        LDR     R0,[R2,#spMode]
        MOV     R1,#VduExt_Log2BPP
        SWI     XOS_ReadModeVariable    ; attempt to read the Log2BPP
        CMP     R2,#3                   ; 8BPP or greater?
        Pull    "R2",GE
        BGE     %FT01
        ADR     R1,default_palette
        LDR     R2,=&45555254           ; "TRUE"
        SWI     XWimp_ReadPalette
        Pull    "R2"                    ; restore R2 after reading the Wimp's palette
        Pull    "PC",VS                 ; and then restore PC if it errors
        B       %FT10

; assuming that the sprite does have a palette or is 256 colours
; we now call ColourTrans to perform the conversion into our nicely
; specified buffer.

01      MOV     R0,R9                   ; R0 -> sprite area to be used
        MOV     R1,R10                  ; R1 -> sprite within the sprite area
        MOV     R5,#1:SHL:0             ; R5 = control flag for ColourTrans (bit 0 =1 => R1 -> sprite)

; assuming that R0,R1 contain meaningful values, if R0 >256 then R5 should
; be setup to contain flags for the sprite conversion.

        ASSERT  (colourtrans_end -colourtrans) >=1024

10      MOV     R2,#-1
        MOV     R3,#-1                  ; R2,R3 =-1 converting to current mode / palette
        ADR     R4,colourtrans          ; R4 -> buffer to fill with PixTrans information

        ORR     R5,R5,#16               ; and ask for a wide table

        SWI     XColourTrans_SelectTable
        Pull    "PC",VS                 ; return if it errored (V set => R0 -> error block)

        ADR     r6,ScaleFactors
        MOV     r0,#0
        STR     r0,[r6,#0]              ; x0 (y1 x1 y1 x1)
        STR     r0,[r6,#20]             ; y0
        STR     r0,[r6,#24]             ; x0
        STR     r0,[r6,#28]             ; y0

        LDR     r0,backdrop_options
        TST     r0,#bd_OptionScaled
        BEQ     %FT01

        ; Scaled sprite, x1,y1 are screen x1,y1
        LDR     r2, XEig                ; Get XEig
        LDR     r0,scale_x1
        MOV     r0,r0,ASL r2
        MOV     r0,r0,ASL #8
        STR     r0,[r6,#8]
        STR     r0,[r6,#16]
        Debug   bd,"x1 = ",r0

        LDR     r2, YEig                ; Get YEig
        LDR     r0,scale_y1
        MOV     r0,r0,ASL r2
        MOV     r0,r0,ASL #8
        STR     r0,[r6,#4]
        STR     r0,[r6,#12]
        Debug   bd,"y1 = ",r0

        LDR     r0,icon_bar_height
        MOV     r0,r0,LSL #8
        STR     r0,[r6,#20]
        STR     r0,[r6,#28]
        B       %FT10

01      ; Not a scaled sprite:

        LDR     r0,scale_x1
        MOV     r0,r0,ASL #8            ; passed in 1/256th of an OS unit
        STR     r0,[r6,#8]
        STR     r0,[r6,#16]
        LDR     r0,scale_y1
        MOV     r0,r0,ASL #8            ; passed in 1/256th of an OS unit
        STR     r0,[r6,#4]
        STR     r0,[r6,#12]

10
        Debug   bd,"Scale factors set."

        LDR     r0,=&200 + SpriteReason_SwitchOutputToSprite
        MOV     r1,#&8000               ; -> Sprite area
        ADD     r2,r1,#16               ; -> Sprite
        MOV     r3,#0                   ; No save area.
        SWI     XOS_SpriteOp
        BVS     %FT99                   ; If error, switch output to screen.

        Debug   bd,"Output switched to sprite"

        LDR     r0, background_colour
        MOV     r3, #128
        MOV     r4, #0
        SWI     ColourTrans_SetGCOL
        SWI     XOS_WriteI+16

        MOV     r0,#&200 + SpriteReason_PutSpriteTransformed
        MOV     r1,r9
        MOV     r2,r10
        MOV     r3,#1                   ; Dest = coords.
        MOV     r5,#8                   ; GCOL action
        ADD     r5,r5,#32               ; wide table
        ADR     r6,ScaleFactors         ; Dest. coords.
        ADR     r7,dataarea             ; Pixel translation table.
        SWI     XOS_SpriteOp

      [ debugbd
        BVS     %FT99
      ]
        Debug   bd,"Sprite scaled."

99
        LDR     r0,=&200 + SpriteReason_SwitchOutputToSprite
        MOV     r2,#0
        MOV     r3,#1
        SWI     XOS_SpriteOp            ; Switch output back to screen.
        Pull    "PC",VS
        Debug   bd,"Output directed back to screen"

; Release any unwanted memory

        LDR     r0,slot_size
        MOV     r1,#-1
        SWI     XWimp_SlotSize
        Pull    "PC",VS

; Now calculate where it would be plotted.

        LDR     r0,backdrop_options
        TST     r0,#bd_OptionScaled
        MOVNE   r0,#0
        STRNE   r0,Sprite_x
        STRNE   r0,Sprite_y             ; For scaled sprites plot at 0,0
        Pull    "PC",NE

        TST     r0,#bd_OptionTiled
        Pull    "PC",NE                 ; For tiled sprites, compute at redraw time.

        MOV     r0,#-1                  ; Current mode

        MOV     r1,#VduExt_XWindLimit   ; Screen width in pixels
        SWI     XOS_ReadModeVariable
        ADDVC   r4,r2,#1
        LDRVC   r2,XEig                 ; XEig
        MOVVC   r4,r4,ASL r2            ; Screen width in OS Units

        MOVVC   r1,#VduExt_YWindLimit   ; Screen height in pixels
        SWIVC   XOS_ReadModeVariable
        ADDVC   r5,r2,#1
        LDRVC   r2,YEig                 ; YEig
        MOVVC   r5,r5,ASL r2            ; Screen height in OS Units

        Pull    "PC",VS

        LDR     r1,icon_bar_height
        SUB     r5,r5,r1

        LDR     r0,scale_x1
        SUBS    r0,r4,r0
        MOV     r0,r0,ASR #1
        STR     r0,Sprite_x

        LDR     r0,scale_y1
        SUBS    r0,r5,r0
        MOV     r0,r0,ASR #1
        ADD     r0,r0,r1
        STR     r0,Sprite_y

        Pull    "PC"

ClearBackdrop
        Push    "r0-r4,lr"
        Debug   pi,"ClearBackdrop"

        LDR     r14,backdrop_options
        BIC     r14,r14,#bd_OptionActive
        STR     r14,backdrop_options

        LDR     r0,backdrop_handle
        MOV     r1,#0
        MOV     r2,#0
        MOV     r3,#&80000
        MOV     r4,#&80000
        SWI     XWimp_ForceRedraw

        LDR     r2,backdrop_path
        TEQ     r2,#0
        MOVNE   r0,#ModHandReason_Free
        SWINE   XOS_Module
        MOV     r1,#0
        STR     r1,backdrop_path

        MOVVC   r0,#0
        MOVVC   r1,#-1
        SWIVC   XWimp_SlotSize

        Pull    "r0-r4,pc"

BackdropSpriteName
        DCB     "Backdrop",0
        ALIGN
        MakeErrorBlock  Pinboard_NoRoom



; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Int_CacheJPEG
;
; Caches a JPEG image used for backdrop
;
; In : r4 = file length (from OS_File call)

Int_CacheJPEG Entry

        LDR     r0, backdrop_options
        ORR     r0, r0, #bd_OptionJPEG
        ORR     r0, r0, #bd_OptionRecache
        STR     r0, backdrop_options

        ; Get memory
        STR     r4, slot_size
        MOV     r3, r4
        ADD     r0, r4, #32             ; Add 32 to file size for luck (or SpriteExtend bug!)
        CMP     r0, #&6000              ; if less than 24k,
        MOVLT   r0, #&6000              ; make it 24k (SpriteExtend bug)
        MOV     r1, #-1
        SWI     XWimp_SlotSize
        MOVVS   r0, #0
        CMP     r0, r3
        BCS     %FT20

        ; Couldn't get the memory
        LDR     r0,backdrop_handle
        MOV     r1,#0
        MOV     r2,#0
        MOV     r3,#&8000
        MOV     r4,#&8000
        SWI     XWimp_ForceRedraw

        ADRL    r0,ErrorBlock_Pinboard_NoRoom
        BL      msgtrans_errorlookup    ; V set on exit

        Pull    "PC"

20      ; Load JPEG
        MOV     r0, #16
        LDR     r1, backdrop_path
        MOV     r2, #&8000
        MOV     r3, #0
        SWI     OS_File
        ; Get width and height
        MOV     r0, #1
        MOV     r1, #&8000
        LDR     r2, slot_size
        SWI     XJPEG_Info
        MOV     r4, r2
        MOV     r5, r3
        ; Read YEig and calculate height in OS units
        LDR     r2, YEig
        MOV     r2,r5, LSL r2
        STR     r2,scale_y1
        ; Read XEig and calculate width in OS units
        LDR     r2, XEig
        MOV     r2,r4, LSL r2
        STR     r2,scale_x1
        ; Are we scaling?
        ADR     r6, ScaleFactors
        LDR     r0, backdrop_options
        TST     r0, #bd_OptionScaled
        BEQ     %FT50

        ; Image is being scaled to fit screen
        ; Set up scale factors
        LDR     r2, Screen_x1
        ADD     r2, r2, #4
        STR     r2, [r6]
        LDR     r2, Screen_y1
        LDR     r0, icon_bar_height
        SUB     r2, r2, r0
        ADD     r2, r2, #4
        STR     r2, [r6, #4]
        LDR     r0, scale_x1
        STR     r0, [r6, #8]
        LDR     r0, scale_y1
        STR     r0, [r6, #12]

        ; Set up position
        MOV     r0, #0
        STR     r0, Sprite_x
        LDR     r0, icon_bar_height
        STR     r0, Sprite_y
        B       %FT60

50      ; Image centred, so scale 1:1
        MOV     r0, #1
        STR     r0, [r6]
        STR     r0, [r6, #4]
        STR     r0, [r6, #8]
        STR     r0, [r6, #12]
        ; Setup x position
        LDR     r0, Screen_x1
        LDR     r1, scale_x1
        SUBS    r2, r0, r1
        MOVS    r3, r2, ASR #1
        STR     r3, Sprite_x
        ; Setup y position
        LDR     r0, Screen_y1
        LDR     r1, scale_y1
        LDR     r4, icon_bar_height
        SUB     r0, r0, r4
        SUBS    r2, r0, r1
        MOVS    r3, r2, ASR #1
        ADD     r3, r3, r4
        STR     r3, Sprite_y
60
        EXIT

        LNK     Icons.s