; 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.
;
; > Sources.SWIs

; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; JPEG_SWI decoding entry point
; Entry: R11 = reason code
;        R12 --> private word
; Exit : R0-R9 may be used to contain results
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

SpriteExtend_SWIDecode
        Debug   gs,"X R0-3",R0,R1,R2,R3
        Debug   gs,"X R4-7",R4,R5,R6,R7
        Debug   gs,"X R8-9,12",R8,R9,R12
      [ debuggs
        Push    "R0"
        MOV     r0, lr
        Debug   gs,"we will return to ",R0
        Pull    "R0"
      ]
        Push    "LR"
        CLRPSR  I_bit,R14                        ; re-enable interrupts

        LDR     r12,[R12]                        ; wsptr --> workspace

        Debug   gs,"R12 = ",R12
        Debug   gs,"R11 = ",R11
        CMP     r11, #2                          ; JPEG_PlotScaled ?
        CMPNE   r11, #3                          ; JPEG_PlotFileScaled ?
        CMPNE   r11, #4                          ; JPEG_PlotTransformed ?
        CMPNE   r11, #5                          ; JPEG_PlotFileTransformed ?
        BNE     swijpnonprinter

        LDR     r14, save_PdriverIntercept
        TST     r14, #1
        BEQ     swijpnonprinter
        Push    "R8"
        AND     r8, r11, #63
        Debug   gs, "I should be calling the printer SWI...",R8
        SWI     XPDriver_JPEGSWI
        Pull    "R8,PC"

swijpnonprinter
        CMP     R11,#maxnewswi
        ADDCC   R14,R11,#(swijptable-swijporg-4)/4
        ADDCC   PC,PC,R14,ASL #2                 ; go!

swijporg
        ADR     R0,ErrorBlock_BadSWI
        BL      copy_error_one
        Pull    "PC"

swijptable
        B       SWIJPEG_Info
        B       SWIJPEG_FileInfo
        B       SWIJPEG_PlotScaled
        B       SWIJPEG_PlotFileScaled
        B       SWIJPEG_PlotTransformed
        B       SWIJPEG_PlotFileTransformed
        B       SWIJPEG_PDriverIntercept
swijptableend
maxnewswi   *   (swijptableend-swijptable)/4

ErrorBlock_BadSWI
        DCD     ErrorNumber_ModuleBadSWI
        DCB     "BadSWI"
        DCB     0
        ALIGN

ErrorBlock_NoFile
        DCD     ErrorNumber_FileNotFound
        DCB     "NoFile"
        DCB     0
        ALIGN

SpriteExtend_SWINames
        DCB     SpriteExtendJPEGSWI_Name,0                ; prefix
        DCB     "Info",0
        DCB     "FileInfo",0
        DCB     "PlotScaled",0
        DCB     "PlotFileScaled",0
        DCB     "PlotTransformed",0
        DCB     "PlotFileTransformed",0
        DCB     "PDriverIntercept",0
        DCB     0
        ALIGN

; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; JPEG_Info
; ---------
; Entry: r0 = flags for desired operation
;             b0 set : return dimensions.
;             b1 set : return SOF type.
;        r1 = Pointer to JPEG image in memory.
;        r2 = length of data in memory (bytes)
; 
; Exit : r0 = returned information flags.
;             b0 set : greyscale image.
;             b1 set : set if transformed plots are not supported.
;             b2 set : pixel density is only a ratio.
;             b3-b6  : SOF type if requested.
;        r1 preserved
;        r2 = width in pixels.
;        r3 = height in pixels.
;        r4 = X pixel density.
;        r5 = Y pixel density
;        r6 = Extra workspace needed to render
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

SWIJPEG_Info
        Pull    "LR"
        Debug   gs,"JPEGInfo: LR =",LR
        Push    "R1-R9,LR"              ; we must stick to the same form of saved registers as 'exitbiggie' assumes,
                                        ; in case of an unexpected exit from the C code.
        Debug   gs, "Image data pointer = ",R1
        MOV     r2, #0                  ; in memory JPEG (r1->data)

jpeginfo_afid
        BICS    r3, r0, #JPEGFlag_Return_Dimensions :OR: JPEGFlag_Return_SOF_Type
        ADRNEL  r0, ErrorBlock_BadFlags
        addr    r1, Title, NE
        BLNE    copy_error_one          ; Always sets the V bit
        BVS     exitbiggie

        STR     sp, ccompiler_sp        ; in case of unexpected exit
        MOV     r4, #0
        STR     r4, ccompiler_errptr    ; in case of error exit

        MOV     r7, r0                  ; keep flags for later
        MOV     r0, r1                  ; move JPEG pointer into r0

        BL      asm_find_image_dims     ; corrupts r0, sets r1-r6
        Pull    "R1-R9,PC", VS
        Debug   gs,"return from C: R1,R2,R3 =",R1,R2,R3

        AND     r0, r1, #3
        TEQ     r0, #3                  ; JPEG Colour = 3, JPEG Mono = 1
        ASSERT  JPEGFlag_Info_Greyscale = 1
        MOVEQ   r0, #0
        TST     r1, #&80                ; Is the pixel density a ratio?
        ORRNE   r0, r0, #JPEGFlag_Info_DensityRatio
        TST     r7, #JPEGFlag_Return_SOF_Type
        MOVNE   r1, r1, LSR #8
        ORRNE   r0, r0, r1, LSL #JPEGFlag_Info_SOF_Shift
        
        ;******THIS MUST BE REMOVED WHEN TRANSFORMATIONS ARE ALLOWED*********
        ORR     r0, r0, #JPEGFlag_Info_NoPlotTransformed
        ;******THIS MUST BE REMOVED WHEN TRANSFORMATIONS ARE ALLOWED*********

        Pull    "R1"
        TST     r7, #JPEGFlag_Return_Dimensions
        LDMEQIA sp, {r2-r3}             ; didn't want the image dimensions after all
        ADDS    sp, sp, #5*4            ; get rid of saved r2-r6 - clear V
        Debug   gs,"returning R0,R1,R2,R3 =",R0,R1,R2,R3
        Debug   gs,"returning R4,R5,R6 =",R4,R5,R6
        Debug   gs,"Got to 12"
        Pull    "R7-R9,PC"              ; copied from exitbiggie, but returning r1-r6 - r0 restored by exit sequence.

        MakeSpriteErrorBlock BadJPEG,,BadJPEG

        MakeSpriteErrorBlock JPEGNoRoom,,JPEGNoRoom

        MakeSpriteErrorBlock JPEGFatal,,JPEGFatal

        MakeSpriteErrorBlock BadJPEGPlot,,BadJPEGPlot

        MakeSpriteErrorBlock BadJPEGUnsupported,,BadJPEGUnsupported

; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; JPEG_FileInfo
; -------------
; Entry: r0 = flags for desired operation
;             b0 set : return dimensions.
;        r1 = pointer to control character terminated filename for
;             JPEG image.
;
; Exit : r0 = returned information flags.
;             b0 set : greyscale image.
;             b1 set : set if transformed plots are not supported.
;             b2 set : pixel density is only a ratio.
;        r1 preserved
;        r2 = width in pixels.
;        r3 = height in pixels.
;        r4 = X pixel density.
;        r5 = Y pixel density
;        r6 = Extra workspace needed to render
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

SWIJPEG_FileInfo
        Pull    "LR"
        Debug   gs,"JPEGFileInfo: LR =",LR
        Push    "R1-R9,LR"              ; we must stick to the same form of saved registers as 'exitbiggie' assumes,
                                        ; in case of an unexpected exit from the C code.
        Debug   gs, "Filename pointer = ",R1
        MOV     r2, #1                  ; in file JPEG (r1->filename)
        B       jpeginfo_afid           ; common tail

; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; JPEG_PlotScaled
; ---------------
; Entry: r0 = pointer to JPEG image in memory
;        r1 = x co-ordinate for plot
;        r2 = y co-ordinate for plot
;        r3 = scale factors or 0
;        r4 = length of data in memory
;        r5 = Flags
;             b0 set: dither output when plotting truecolour in 8bpp or less.
;             b1 set: Full error-diffusion when plotting to 8bpp.
;
; Exit : all registers preserved.
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

SWIJPEG_PlotScaled
        Pull    "LR"
        Push    "R1-R9,LR"              ; we must stick to the same form of saved registers as 'exitbiggie' assumes,
      [ debuggs
        MOV     r1, sp
        Debug   gs,"sp after push 1-9+lr =", r1
        Debug   gs,"JPEG_PlotScaled sprite: R0,R1,R2 =",R0,R1,R2
        Debug   gs,"JPEG_PlotScaled sprite: R3,R4,R5 =",R3,R4,R5
        ADRL    r3, newtranstable
        Debug   gs,"newtranstable at ",r3
      ]
        MOV     R1, R0
        MOV     R2, R4

        BICS    r3, r5, #JPEGFlag_Scaled_Dither_Enable :OR: JPEGFlag_Scaled_Error_Diffused_Dither
        ADRNEL  R0, ErrorBlock_BadFlags
        addr    r1, Title, NE
        BLNE    copy_error_one          ; Always sets the V bit
        BVS     exitbiggie

        AND     r3, r5, #JPEGFlag_Scaled_Dither_Enable :OR: JPEGFlag_Scaled_Error_Diffused_Dither
        STR     r3, dither_truecolour
        Debug   gs,"Storing in dither...R3 = ",R3

        ; Set escape stack level in case of unexpected exit from C code.
        STR     SP,ccompiler_sp         ; in case of unexpected exit
        MOV     R4,#0
        STR     R4,ccompiler_errptr     ; in case of error exit

        ; Space is allocated on the stack, as follows:
        ;   saved registers R1-R9,LR so that exitbiggie can come back to us
        ;   jpeg pointer - 11th register
        ;   a 32K translation table - from ColourTrans
        ;   a fake sprite control block
        ;   16 bytes immediately following the fake sprite of JPEG credentials (compress_id_words)
        ;            +0 id
        ;            +4 pointer to jpeg
        ;            +8 length of jpeg
        ;            +C amount of workspace to decompress jpeg
        ^       0, sp
pjs_start       #       0
pjs_savearea    #       10*4
pjs_r0save      #       4
pjs_table       #       12
pjs_sprite      #       SpriteCBsize
pjs_compressid  #       16
pjs_end         #       0
        SUB     sp,sp,#pjs_end-pjs_start          ; allocate that space

        ; The sprite header sits on the stack. A sprite header consists of:
        ;   spNext    # 4  ;  Offset to next sprite
        ;   spName    # 12 ;  Sprite name
        ;   spWidth   # 4  ;  Width in words-1      (0..639)
        ;   spHeight  # 4  ;  Height in scanlines-1 (0..255/511)
        ;   spLBit    # 4  ;  First bit used (left end of row)
        ;   spRBit    # 4  ;  Last bit used (right end of row)
        ;   spImage   # 4  ;  Offset to sprite image
        ;   spTrans   # 4  ;  Offset to transparancy mask
        ;   spMode    # 4  ;  Mode sprite was defined in
        ;   spPalette # 0  ;   
        MOV     r0,#spPalette+100
        STR     r0,pjs_sprite+spNext               ; look realistic for SWI calls that read this header
        MOV     r0,#'x'
        STR     r0,pjs_sprite+spName               ; terminated by a zero character

        MOV     r0,#0
        STR     r0,pjs_sprite+spLBit
        MOV     r0,#31
        STR     r0,pjs_sprite+spRBit               ; number of bits used in right hand word at 32bpp

        MOV     r0,#spPalette                      ; not paletted
        STR     r0,pjs_sprite+spImage
        STR     r0,pjs_sprite+spTrans

        MOV     r0, #1                             ; set mode number
        MOV     r3, #90
        ORR     r0, r0, r3, LSL #1                 ; Horizontal dpi
        ORR     r0, r0, r3, LSL #14                ; Vertical dpi
        ORR     r0, r0, #SpriteType_JPEG :SHL: 27  ; Sprite Type = 9
        STR     r0,pjs_sprite+spMode

        MOV     r0,#-1
        Debug   gs,"compress id words: R0,R1,R2 =",R0,R1,R2
        ASSERT  (pjs_sprite + SpriteCBsize) = pjs_compressid
        STR     r0,pjs_compressid+0                ; store identifier for in memory JPEG data.
        STR     r1,pjs_compressid+4                ; store pointer to JPEG data.
        STR     r1,pjs_r0save
        STR     r2,pjs_compressid+8                ; store length of JPEG data

        ; Call find_image_dims to find the dimensions of the JPEG,
        ; and use this to fill in the rest of the sprite header.
        MOV     r0, r1                             ; get pointer to JPEG
        MOV     r2, #0                             ; clear r2 because image is in memory
        BL      asm_find_image_dims                ; corrupts r0, sets r1-r6
        BVS     jpegscaled_errorexit
        Debug   gs,"found dims... R1,R2,R3,R6=",R1,R2,R3,R6

        STR     r6,pjs_compressid+12               ; store workspace requirements to work on this JPEG

        SUB     r3,r3,#1
        STR     r3,pjs_sprite+spHeight             ; height in scanlines - 1

        SUB     r2,r2,#1
        STR     r2,pjs_sprite+spWidth              ; number of words - 1 at 32bpp

        ; Call ColourTrans to get a suitable translation table for sending 32-bit data
        ; into this screen mode. This is either a 32K table, or no table at all.
        ; If this produces an error then we're probably on RISC OS 3.1,
        ; in which case we go forward with no translation table.
        LDR     r0, ctrans_recent
        TEQ     r0, #0
        MOVEQ   r7,#0                              ; error return - not new ColourTrans
        BEQ     %FT01

        MOV     r0,#SpriteType_New32bpp :SHL: 27
        ORR     r0,r0,#1                           ; new mode number for 32bpp
        MOV     r1,#-1                             ; default input, output, palette, everything
        MOV     r2,#-1
        MOV     r3,#-1
        ADR     r4,pjs_table                       ; pointer to buffer to put table in
        MOV     r5,#0                              ; no special flags
        MOV     r6,#0
        MOV     r7,#0
        SWI     XColourTrans_SelectTable
        BVS     jpegscaled_errorexit               ; error return, no table about
        ADR     r7,pjs_table                       ; table to use now in r7, all through following code
        Debug   gs,"Generated trans table at ",R7
01
        ; Set up the output from readvduvars and readspritevars
        BL      readvduvars                        ; r7 undisturbed
        BVS     jpegscaled_errorexit

        ; This stuff is copied from readspritevars
        MOV     R3,#5                   ; log2 of 32
        STR     R3,save_inlog2bpc
        STR     R3,save_inlog2bpp
        MOV     R3,#1:SHL:5             ; bits per pixel
        STR     R3,save_inbpp
        MOV     R3,#1                   ; log2 of 2 OS-units
        Debug   gs,"inlog2px: R3=",R3
        STR     R3,inlog2px             ; pretend to be VGA-size pixels
        STR     R3,inlog2py             ; pretend to be VGA-size pixels
        STR     R3,is_it_jpeg           ; mark as a JPEG sprite
        MOV     R0,#20
        STR     R0,inmode               ; the mode vars are for mode 20 sprites.

      [ dynamicarea
        ; Update the area size incase the user resized it since last time
        LDR     r0, area_number
        MOVS    r2, r0
        BEQ     %FT10                   ; no area yet
        SWI     XOS_ReadDynamicArea     ; find out how big area is
        MOVVS   r1, #0                  ; area vanished (pretend zero size)
        MOVS    r2, r1                  ; area resized to nothing
        LDRNE   r2, jpeg_info_ptr
        STRNE   r1, [r2, #workspace_size]
10
        STR     r2, jpeg_info_ptr
      ]
        ; Now set up the registers to enter the regular PutSpriteScaled code
        ; r7 is still the translation table to use
        ADR     r0,pjs_end              ; reach round the pjs frame to get at original saved registers
        LDMIA   r0,{r1-r6}
        ADR     lr,jpegscaled_exit
      [ debuggs
        MOV     r0,lr
        Debug   gs,"Lr for ret=",r0
      ]
        ASSERT  pjs_start = pjs_savearea
        STMIA   sp,{r1-r9,lr}           ; save state for cleanup-and-exit
        Debug   gs,"pjs sprite: R0,R1,R2 =",R0,R1,R2
        Debug   gs,"pjs sprite: R3,R4,R5 =",R3,R4,R5
        Debug   gs,"pjs sprite: R6,R7 =",R6,R7
        MOV     r6,r3                   ; put scale in r6
        MOV     r3,r1                   ; put x-coord in r3
        MOV     r0,r2                   ; temp r2
        MOV     r2,r4                   ; put size in r2
        MOV     r4,r0                   ; put y-coord in r4
        MOV     r5,#0                   ; only plot action of 0 allowed (eg no XOR etc.)
        ADR     r1,pjs_sprite           ; the fake sprite
        STR     R1,save_sprite          ; so that later code can find the JPEG data again
        MOV     R8,#0                   ; no printer calibration table
        STR     R8,calibration_table
        Debug   gs,"pjs sprite: R0,R1,R2 =",R0,R1,R2
        Debug   gs,"pjs sprite: R3,R4,R5 =",R3,R4,R5
        Debug   gs,"pjs sprite: R6,R7 =",R6,R7
        B       putsprscaled_frompjs

        ; We come to here from exitbiggie, after either an error or plotting the sprite.
        ; Just drop the stack, and exit.
jpegscaled_exit
      [ debuggs
        MOV     r1, sp
        Debug   gs, "We returned to the right place",R1
      ]
        LDR     r0,ccompiler_errptr
        CMP     r0, #0                            ; did C code return an error?
        BNE     %FT20
      [ debuggs
        MOV     r1, sp
        Debug   gs,"ok1. sp = ",r1
      ]
        ADD     sp,sp,#pjs_end-pjs_table          ; junk the fake sprite and colourtrans table
        Pull    "R0"                              ; original R0 (pjs_jpegdata)
        Debug   gs,"r0 when loaded =",R0
      [ debuggs
        MOV     r1, sp
        Debug   gs,"ok23. sp = ",r1
      ]
        Pull    "R1-R9,LR"                        ; restore others (pjs_savearea)
        Debug   gs,"X R0-3",R0,R1,R2,R3
        Debug   gs,"X R4-7",R4,R5,R6,R7
        Debug   gs,"X R8-9",R8,R9
        MOV     pc, lr
20
        ADD     sp,sp,#4                          ; junk pjs_jpegdata
        SUB     sp,sp,#pjs_table-pjs_start        ; correct for the ADD in 'jpegscaled_errorexit' moving stack too far.
        TST     r0, #2                            ; C code returned bad jpeg error
        BNE     jpegscaled_errorexit1
        TST     r0, #4                            ; C code bombed out with Fatal error
        BNE     jpegscaled_errorexit2             ; Otherwise must have a "Run out of memory" error

jpegscaled_errorexit0
        Debug   gs, "We think we'be run out of memory"
        ADRL    R0,ErrorBlock_JPEGNoRoom
        Debug   gs,"error block at r0 = ",R0
        BL      copy_error_one
        B       jpegscaled_errorexit
jpegscaled_errorexit1
        Debug   gs, "We think we've got a duff JPEG"
        ADRL    R0,ErrorBlock_BadJPEG
        Debug   gs,"error block at r0 = ",R0
        BL      copy_error_one
        B       jpegscaled_errorexit
jpegscaled_errorexit2
        Debug   gs, "We think we've had a fatal error"
        ADRL    R0,ErrorBlock_JPEGFatal
        Debug   gs,"error block at r0 = ",R0
        BL      copy_error_one
        
jpegscaled_errorexit
      [ debuggs
        MOV     r1, sp
        Debug   gs,"1. sp = ",r14
        MOV     r4, #pjs_end-pjs_start
        Debug   gs,"pjs size = ",R4
      ]
        ADD     sp,sp,#pjs_end-pjs_start          ; free that space
      [ debuggs
        MOV     r4, sp
        Debug   gs,"2. sp = ",r4
      ]
        Pull    "R1-R9,LR"
        Debug   gs,"r0 is now (at end...) = ",R0
        Debug   gs,"X R0-3",R0,R1,R2,R3
        Debug   gs,"X R4-7",R4,R5,R6,R7
        Debug   gs,"X R8-9,12",R8,R9,R12
      [ debuggs
        MOV     r4, lr
        Debug   gs,"about to return to ",R4
      ]
        MOV     pc, lr

; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; JPEG_PlotFileScaled
; -------------------
; Entry: r0 = pointer to control character terminated filename
;        r1 = x co-ordinate for plot
;        r2 = y co-ordinate for plot
;        r3 = scale factors or 0
;        r4 = Flags
;             b0 set: dither output when plotting truecolour in 8bpp or less.
;             b1 set: Full error-diffusion when plotting to 8bpp.
;
; Exit : all registers preserved.
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

SWIJPEG_PlotFileScaled
        BICS    LR, r4, #JPEGFlag_Scaled_Dither_Enable :OR: JPEGFlag_Scaled_Error_Diffused_Dither
        ADRNEL  R0, ErrorBlock_BadFlags
        addr    r1, Title, NE
        BLNE    copy_error_one           ; Always sets the V bit
        Pull    "PC", VS

        Pull    "LR"
        Push    "R0,R4-R6,LR"
        Push    "R1-R4"

        ; Find out file size.
        MOV     r1, r0
        MOV     r0, #OSFile_ReadWithTypeNoPath
        SWI     XOS_File
        CMP     r0, #object_nothing
        BEQ     jpegplotfilescaled_nofile
        Debug   gs,"File size =", r4

        ; Claim space for buffer from Module area.
        MOV     r0, #ModHandReason_Claim
        MOV     r3, r4                   ; size of JPEG buffer
        SWI     XOS_Module               ; pointer to block now in r2
        Debug   gs,"Block for JPEG =", R2
        BVS     jpegplotfilescaled_error ; jump out and return error.

        ; Read file into buffer
        MOV     r6, r2                   ; Move r2 to r6 because r2 gets changed by OS_FILE
        MOV     r3, #0                   ; clear r3 so r2 used as load address
        MOV     r0, #OSFile_LoadNoPath
        Debug   gs,"Loading file: r0,r1,r2,r3 =", R0,R1,R2,R3
        SWI     XOS_File                 ; file name still in r1
        BVS     jpegplotfilescaled_error ; jump out and return error.

        Debug   gs,"Load address = ",R6
        MOV     r0, r6
        Pull    "R1-R3,R5"               ; pull original parameters into correct regs for JPEG_plotscaled.
        Push    "R6"                     ; store address of buffer so we can free it.
        ADR     LR, jpegplotscaled_return
        Push    "LR"
        Debug   gs,"Calling PlotScaled: R0,R1,R2,R3,R4,R5=",R0,R1,R2,R3,R4,R5
        B       SWIJPEG_PlotScaled

jpegplotscaled_return
        Debug   gs,"Return From PlotScaled: R0,R1,R2,R3=",R0,R1,R2,R3
        MOVVS   r4, #1                   ; keep record of error after next SWI call.
        MOVVC   r4, #0
jpegplotfilescaled_exit1
        MOV     r5, r0                   ; temporarily store r0 and r2
        MOV     r6, r2
        Pull    "R2"                     ; recover location of buffer from stack
        MOV     r0, #ModHandReason_Free
        SWI     XOS_Module               ; Free module space
        BVS     jpegplotfilescaled_error2; jump out and return error.
        MOV     r0, r5                   ; recover original r0 and r2
        MOV     r2, r6
        CMP     r4, #1                   ; Did SWIJPEG_PlotScaled return an error?
        Pull    "R0,R4-R6,PC",NE         ; Nope
        SETV                             ; If so, make sure the V flag is set.
        B       jpegplotfilescaled_error2

jpegplotfilescaled_nofile
        ADRL    R0,ErrorBlock_NoFile
        Pull    "R1-R4"
        MOV     r4, r1
        Pull    "R1"                     ;should be r0 saved at start...
        BL      copy_error_one
        MOV     r1, r4
        Pull    "R4-R6,PC"

jpegplotfilescaled_error
        Pull    "R1-R4"
        Debug   gs,"about to return from filescaled..."

jpegplotfilescaled_error2
        ADD     sp, sp, #4
        Pull    "R4-R6,PC"

; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; JPEG_PlotTransformed
; --------------------
; Entry: R0 = Pointer to JPEG file loaded in Memory
;        R1 = flag word
;                b0 set: R2 is pointer to dest. coords, else pointer to matrix
;                b1 set: dither output when plotting truecolour in 8bpp or less.
;                b2 set: Full error-diffusion when plotting to 8bpp.
;        R2 = pointer to matrix (as for Draw module) or
;             pointer to destination co-ordinate block.
;        R3 = length of data in memory.
;
; Exit : all registers preserved.
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

SWIJPEG_PlotTransformed
        Pull    "LR"
        Push    "R0-R11,LR"
        BICS    r4, r1, #JPEGFlag_Transformed_Coords_In_R2 :OR: JPEGFlag_Transformed_Dither_Enable :OR: JPEGFlag_Transformed_Error_Diffused_Dither
        Pull    "R0-R11", NE
        ADRNEL  R0, ErrorBlock_BadFlags
        addr    r1, Title, NE
        BLNE    copy_error_one          ; Always sets the V bit
        Pull    "PC", VS

        TST     r1, #1
        BNE     jpegtrans_destcoords

        ; Matrix
        LDR     r4, [r2, #4]            ; Rotation value
        CMP     r4, #0
        Debug   gs,"Rot value 1..",R4
        BNE     jpegtrans_errorexit
        LDR     r4, [r2, #8]            ; Rotation value
        CMP     r4, #0
        Debug   gs,"Rot value 2..",R4
        BNE     jpegtrans_errorexit
        LDR     r4, [r2]                ; X scale factor in Draw Transform units
        CMP     r4, #0
        BMI     jpegtrans_errorexit
        LDR     r4, [r2, #12]           ; Y scale factor in Draw Transform units
        CMP     r4, #0
        BMI     jpegtrans_errorexit

        ; Make up scale factor...
        Debug   gs,"scale factors are...",R7,R8,R2,R3
        Push    "R0-R2"
        MOV     r0, #-1
        MOV     r1, #VduExt_XEigFactor
        SWI     XOS_ReadModeVariable    ; Get X Eig in R2
        MOV     r7, r2                  ; Put into r7
        MOV     r1, #VduExt_YEigFactor
        SWI     XOS_ReadModeVariable    ; Get Y Eig in R2
        MOV     r8, r2                  ; Put into r8
        Pull    "R0-R2"
        SUB     sp, sp, #16             ; make room for scale factors
        LDR     r4, [r2]                ; X scale factor in Draw Transform units
        STR     r4, [sp]
        LDR     r4, [r2, #12]           ; Y scale factor in Draw Transform units
        STR     r4, [sp,#4]
        MOV     r6, #180                ; Dpi of 1 pixel per OS unit sprite.
        MOV     r7, r6, LSR r7          ; X Dpi of output sprite
        MOV     r8, r6, LSR r8          ; Y Dpi of output sprite
        Push    "R1-R6"

        ; JPEG pointer already in r0
        MOV     r2, #0
        BL      asm_find_image_dims

        MOV     r9, r4
        MOV     r10, r5
        Pull    "R1-R6"

        ; *************************************************
        ; ***  DivRem - Integer division and remainder  ***
        ; ***  rc := ra DIV rb; ra := ra REM rb         ***
        ; ***  rb preserved, rtemp corrupt              ***
        ; ***  DivRem   rc, ra, rb, rtemp               ***
        ; *************************************************
        
        ; We need to use a ratio of Output dpi to input dpi to convert
        ; the OS unit to OS unit scale factor from matrix to a pixel to
        ; pixel scale factor which we can send to PlotScaled.
        MOV     r4, r9, LSL #16         ; X input dpi * 2^16 (because of
                                        ; transform coordinates)
        DivRem  r5, r4, r7, r9          ; r5 = xdivisor div outdpi
        STR     r5, [sp,#8]
        MOV     r4, r10, LSL #16        ; X input dpi * 2^16 (because of
                                        ; transform coordinates)
        DivRem  r5, r4, r8, r9          ; r5 = xdivisor div outdpi
        STR     r5, [sp,#12]
        
        ; Set up registers for PutScaled Call
        MOV     r4, r3
        MOV     r3, sp                  ; Pointer to Scale factors
        MOV     r5, r1, LSR #1
        LDR     r1, [r2, #16]           ; X-coordinate in 1/256th OSunit
        MOV     r1, r1, ASR #8
        LDR     r2, [r2, #20]           ; Y-coordinate in 1/256th OSunit
        MOV     r2, r2, ASR #8
        Debug   gs,"Calliing PutScaled.R0,R1,R2,R3,R4,R5=",R0,R1,R2,R3,R4,R5
        ADRL    lr, jpegtrans_plotreturn
        Push    "LR"
        BL      SWIJPEG_PlotScaled

jpegtrans_destcoords
        Debug   gs,"Doing a DestCoords Plot Transformed"
        MOV     r11, r1

        ; Check output coord block is a rectangle
        LDR     r4, [r2]                ; X0
        Debug   gs,"load 1 ",r4
        LDR     r5, [r2, #24]           ; X3
        Debug   gs,"load 2 ",r5
        CMP     r4, r5
        BNE     jpegtrans_errorexit
        Debug   gs,"Check 1 passed"
        LDR     r4, [r2, #4]            ; Y0
        LDR     r5, [r2, #12]           ; Y1
        CMP     r4, r5
        BNE     jpegtrans_errorexit
        Debug   gs,"Check 2 passed"
        LDR     r4, [r2, #20]           ; Y2
        LDR     r5, [r2, #28]           ; Y3
        CMP     r4, r5
        BNE     jpegtrans_errorexit
        Debug   gs,"Check 3 passed"
        LDR     r4, [r2, #8]            ;X1
        LDR     r5, [r2, #16]           ;X2
        CMP     r4, r5
        BNE     jpegtrans_errorexit
        Debug   gs,"Check 4 passed"
        LDR     r4, [r2]                ; X0
        CMP     r4,r5                   ; which one is biggest?
        BGT     jpegtrans_errorexit     ; can't allow flipping...
        Debug   gs,"Check 5 passed"
        LDR     r6, [r2, #4]            ; Y0
        LDR     r7, [r2, #28]           ; Y3
        CMP     r7,r6                   ; which one is biggest?
        BGT     jpegtrans_errorexit     ; can't allow flipping...
        Debug   gs,"Check 6 passed"
        SUB     r4, r5, r4              ; dest X-size in r4 in 1/256th OS units
        SUB     r5, r6, r7              ; dest Y-size in r5 in 1/256th OS units
        MOV     r4, r4, LSR #8          ; dest X-size in r4 in OS units
        MOV     r5, r5, LSR #8          ; dest Y-size in r5 in OS units
        ; convert dest size from OS units to pixels
        Debug   gs,"Plot dosen't include any rotation or flipping"
        Push    "R0-R2"
        MOV     r0, #-1
        MOV     r1, #VduExt_XEigFactor
        SWI     XOS_ReadModeVariable    ; Get X Eig in R2
        MOV     r7, r4, LSR r2          ; Dest X-Size in pixels
        MOV     r1, #VduExt_YEigFactor
        SWI     XOS_ReadModeVariable    ; Get Y Eig in R2
        MOV     r8, r5, LSR r2          ; Dest Y-Size in pixels
        Pull    "R0-R2"
        MOV     r9, r2                  ; temp store of pointer to coord block;
        MOV     r10, r3                 ; temp store of length of data;
        ; find size of JPEG
        MOV     r1, r0                  ; pointer to JPEG
        MOV     r0, #1
        MOV     r2, r3                  ; length.
        ADRL    lr, jpegtrans_inforeturn
        Push    "LR"
        B       SWIJPEG_Info

        ; Make up scale factor...
jpegtrans_inforeturn
        Debug   gs,"scale factors are...",R7,R8,R2,R3
        SUB     sp, sp, #16             ; make room for scale factors
        STR     r7, [sp]
        STR     r8, [sp,#4]
        STR     r2, [sp,#8]
        STR     r3, [sp,#12]
        ; Set up registers for PutScaled Call
        MOV     r3, sp                  ; Pointer to Scale factors
        MOV     r0, r1                  ; Pointer to JPEG
        LDR     r1, [r9]                ; X-coordinate in 1/256th OSunit
        MOV     r1, r1, ASR #8
        LDR     r2, [r9,#28]            ; Y-coordinate in 1/256th OSunit
        MOV     r2, r2, ASR #8
        MOV     r4, r10
        MOV     r5, r11, LSR #1
        Debug   gs,"Calling PutScaled.R0,R1,R2,R3,R4,R5=",R0,R1,R2,R3,R4,R5
        ADRL    lr, jpegtrans_plotreturn
        Push    "LR"
        BL      SWIJPEG_PlotScaled

jpegtrans_plotreturn
        ; what if error returned?
        ADDVS   sp, sp, #16
        BVS     jpegtrans_errorexit1
        ; recover stack space
        Debug   gs,"Returned from putscaled"
        ADD     sp, sp, #16
        Pull    "R0-R11,PC"

jpegtrans_errorexit
        ADRL    R0,ErrorBlock_BadJPEGPlot
        BL      copy_error_one
        Debug   gs,"Done 'copy_error_one'"

jpegtrans_errorexit1
        ADD     sp, sp, #4                      ;Skip over r0
        Pull    "R1-R11,PC"

; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; JPEG_PlotFileTransformed
; ------------------------
; Entry: R0 = Pointer to control charater terminated filename for JPEG image
;        R1 = flag word
;                b0 set: R2 is pointer to dest. coords, else pointer to matrix
;                b1 set: dither output when plotting truecolour in 8bpp or less.
;                b2 set: Full error-diffusion when plotting to 8bpp.
;        R2 = pointer to matrix (as for Draw module) or
;             pointer to destination co-ordinate block.
;
; Exit : all registers preserved.
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

SWIJPEG_PlotFileTransformed
        Pull    "LR"
        Push    "R0,R3-R6,LR"
        BICS    r3, r1, #JPEGFlag_Transformed_Coords_In_R2 :OR: JPEGFlag_Transformed_Dither_Enable :OR: JPEGFlag_Transformed_Error_Diffused_Dither
        Pull    "R0,R3-R6", NE
        ADRNEL  R0, ErrorBlock_BadFlags
        addr    r1, Title, NE
        BLNE    copy_error_one           ; Always sets the V bit
        Pull    "PC", VS

        Push    "R1-R3"

        ; Find out file size.
        MOV     r1, r0
        MOV     r0, #OSFile_ReadWithTypeNoPath
        SWI     XOS_File
        CMP     r0, #object_nothing
        BEQ     jpegplotfiletrans_nofile
        Debug   gs,"File size =", r4

        ; Claim space for buffer from Module area.
        MOV     r0, #ModHandReason_Claim
        MOV     r3, r4                   ; size of JPEG buffer
        SWI     XOS_Module               ; pointer to block now in r2
        Debug   gs,"Block for JPEG =", R2
        BVS     jpegplotfiletrans_error  ; jump out and return error.

        ; Read file into buffer
        MOV     r6, r2                   ; Move r2 to r6 because r2 gets changed by OS_FILE
        MOV     r3, #0                   ; clear r3 so r2 used as load address
        MOV     r0, #OSFile_LoadNoPath
        Debug   gs,"Loading file: r0,r1,r2,r3 =", R0,R1,R2,R3
        SWI     XOS_File                 ; file name still in r1
        BVS     jpegplotfiletrans_error  ; jump out and return error.
        Debug   gs,"Load address = ",R6
        MOV     r3, r4
        MOV     r0, r6
        Pull    "R1-R2,R4"               ; pull original parameters into correct regs for JPEG_plotTransformed.
        Push    "R6"                     ; store address of buffer so we can free it.
        ADR     LR, jpegplottrans_return ; set up return from plot code.
        Push    "LR"
        Debug   gs,"Calling PlotTransformed: R0,R1,R2,R3,R4,R5=",R0,R1,R2,R3,R4,R5
        B       SWIJPEG_PlotTransformed

jpegplottrans_return
        Debug   gs,"Return From PlotTransformed: R0,R1,R2,R3=",R0,R1,R2,R3
        MOVVS   r4, #1                  ;keep record of error after next SWI call.
        MOVVC   r4, #0

jpegplotfiletrans_exit1
        MOV     r5, r0                  ; temporarily store r0 and r2
        MOV     r6, r2
        Pull    "R2"                    ; recover location of buffer from stack
        MOV     r0, #ModHandReason_Free
        SWI     XOS_Module              ; Free module space
        BVS     jpegplotfiletrans_error2; jump out and return error.
        MOV     r0, r5                  ; recover original r0 and r2
        MOV     r2, r6
        CMP     r4, #1                  ; Did SWIJPEG_PlotTransformed return an error?
        BNE     jpegplotfiletrans_exit2
        SETV                            ; If so, make sure the V flag is set.
        B       jpegplotfiletrans_error2
        
jpegplotfiletrans_exit2
        Pull    "R0,R3-R6,PC"

jpegplotfiletrans_nofile
        ADRL    R0,ErrorBlock_NoFile
        Pull    "R1-R3"
        MOV     r4, r1
        Pull    "R1"                     ;should be r0 saved at start...
        BL      copy_error_one
        MOV     r1, r4
        Pull    "R3-R6,PC"

jpegplotfiletrans_error
        Pull    "R1-R3"
        Debug   gs,"about to return from fileTransformed..."
jpegplotfiletrans_error2
        ADD     sp, sp, #4
        Pull    "R3-R6,PC"

; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; JPEG_PDriverIntercept
;----------------------
; Entry: R0 = flags
;             b0 = intercept state; 0 = off, 1 = on
;             b1 = set: plot all JPEGs using translation table
;             b2-31 reserved (set to 0)
;
; Exit : all registers preserved.
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

SWIJPEG_PDriverIntercept
        Debug   gs,"Pdriver Intercept called...."
        Push    "R1"
        LDR     r1, save_PdriverIntercept
        AND     r0, r0, #JPEGFlag_Intercept_Pass_On_Plots :OR: JPEGFlag_Intercept_Use_Translation_Table
        STR     r0, save_PdriverIntercept
        Debug   gs, "Setting the Pdriver intercept flag to ...",R0
        MOV     r0, r1
        Pull    "R1,PC"

        ; Entry:  r0 points to JPEG/filename
        ;         r2 = 0 for JPEG in memory/1 for file
        ;         exit level for C panic set up
        ; Exit:   r1 = image type in bits 0 & 1, ratio in bit 7, SOF type in bits 8-11
        ;         r2 = width
        ;         r3 = height
        ;         r4 = X density
        ;         r5 = Y density
        ;         r6 = memory required
asm_find_image_dims ROUT
        Push    "R0,SL,LR"
        SUB     sp, sp, #20             ; space for image_dims_info structure and ws_size
      [ dynamicarea
        MOV     r4, r0
        MOV     r5, r2
        ; Update the area size incase the user resized it since last time
        LDR     r0, area_number
        MOVS    r2, r0
        BEQ     %FT10                   ; no area yet
        SWI     XOS_ReadDynamicArea     ; find out how big area is
        MOVVS   r1, #0                  ; area vanished (pretend zero size)
        MOVS    r2, r1                  ; area resized to nothing
        LDRNE   r2, jpeg_info_ptr
        STRNE   r1, [r2, #workspace_size]
10
        STR     r2, jpeg_info_ptr
        MOV     r1, r2
        MOV     r0, r4                  ; put regs back where they should be
        MOV     r2, r5
      |
        LDR     r1, jpeg_info_ptr
      ]
        STR     r1, [sp]
        ORR     r2, sp, r2              ; r2->int (for ws_size plus flags in bits 0 & 1)
        ADD     r1, sp, #1*4            ; r1->image_dims_info structure
                                        ; r0->jdata
        MOV     sl, r12                 ; will be left alone by compiled C - for debug routines above.
        Debug   gs,"calling find_image_dims: R0,R1,R2,R3 =",R0,R1,R2,R3

        BL      find_image_dims         ; dive into the C - returns 0 in r0 if all is well.

        Debug   gs,"just returned: R0 =",R0
        MOV     r12, sl                 ; R12 is ip to a C prog, will have been trampled on - restore it.
        CMP     r0, #2
        BHI     %FT99                   ; an OS error to pass on
        ADREQL  r0, ErrorBlock_BadJPEGUnsupported
        BEQ     %FT98                   ; Is JPEG but not supported
        TEQ     r0, #1
        ADREQL  r0, ErrorBlock_BadJPEG
        BEQ     %FT98                   ; Is not JPEG
        
        LDMIA   sp, {r0,r1-r4}          ; get memory requirements; image type; width; height; packed density
        MOV     r6, r0                  ; memory requirements in right register
        
        Debug   gs, "type = ",R1
        Debug   gs, "width, height = ",R2,R3
        MOV     r5, r4, LSL #16         ; put density into 2 separate regs.
        MOV     r5, r5, LSR #16
        MOV     r4, r4, LSR #16
        Debug   gs, "xdens, ydens =",R4,R5
        ADDS    sp, sp, #20             ; get rid of stack workspace & clear V
        Pull    "R0,SL,PC"
98
        BL      copy_error_one        
99
        SETV
        ADD     sp, sp, #20             ; get rid of stack workspace
        Debug   gs,"r0(err) =",R0
        ADD     sp, sp, #4              ; skip over stored version of r0
        Pull    "SL,PC"                 ; pull up other two

        END