; 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.CFSI-JPEG
; This makes an image of assembler code that can be loaded in by ChangeFSI
; and then called, to decode a JPEG file.

; At the start of the image are defined entrypoints.
; Conditions for entering these are:
;   lr = return address
;   sp -> a useable stack
;   r0..r3 = arguments (could be more on stack)
; On exit:
;   r0 will contain a returned result, if defined
;   r1..r3, lr will be trashed
;   all other registers will be preserved

        AREA    |!!!ChangeFSISupport$$Code|, CODE, READONLY, PIC

        B       cfsi_jpeg_scan_file
        B       cfsi_jpeg_find_line
        B       cfsi_find_image_dims
        B       cfsi_jpeg_scan_file_16
        DCD     3                        ; version number.

        GET     Hdr:ListOpts
        GET     Hdr:Macros
        GET     Hdr:System
        GET     Hdr:ColourTran
        GET     sources.csupport

; We cope with the whole 26/32-bit thing thus:

; All our C code is APCS-32. The routines like newline() and assert() called
; from our C thus are 32-bit. We don't know about the person using the generated
; CFSI-JPEG file, so we do a run-time check for whether to do a ^ or not on
; return, depending on current mode, in the outer wrapper.

cfsi_jpeg_scan_file
; Entry conditions: r0 -> space (word-aligned)
;                   r1 = size of space (bytes)
;                   r2 -> file image in store
;                   r3 = file image length
        STMDB   sp!,{r1-r12,lr}
        MOV     sl,sp                 ; used to remember panic exit point
        BL      do_jpeg_scan_file
        TEQ     pc, pc
        TEQ     pc, pc
        LDMNEIA sp!,{r1-r12,pc}^      ; 26-bit: safe
        LDMIA   sp!,{r1-r12,pc}
; All registers preserved except r0. r0=error code, 0 for OK or other for some error.
; On exit the workspace has some interesting fields at the front:
;struct decompress_info_struct {
;        int error_code;         /* Returned err code, 0 if no error */
;        int error_argument1;    /* Supplementary error data */
;        int error_argument2;    /* Supplementary error data */
;        int a;                        /* don't touch this */
;        int b;                        /* don't touch this */
;        int /*long*/ image_width;     /* overall image width */
;        int /*long*/ image_height;    /* overall image height */
;        COLOR_SPACE jpeg_color_space; /* colorspace of JPEG file */
; ... never mind about the rest
; If all is well on exit then error_code will be 0.
; Otherwise it (and r0) is one of:
;#define E_PRE_NOT_8         1            /* Data precision not 8 */
;#define E_RESTART           2            /* Restart interval not 0 */
;#define E_MULTI_SCAN        3            /* Multi-scan file */
;#define E_TOO_HIGH          4            /* Image too high, max is %i pixels */
;#define E_BAD_SAMPLE        5            /* Bad sample factor */
;#define E_COLOUR            8            /* Bad colour space (%i), not grey or YUV */
;#define E_COMPONENTS        9            /* Bad number (%i) of components, only 1 or 3 allowed */
;#define E_TOO_WIDE          10           /* Image too wide, max is %i pixels */
; The colour space will be 1 for greyscale, 3 for YUV.

cfsi_jpeg_scan_file_16
; Entry conditions: r0 -> space (word-aligned)
;                   r1 = size of space (bytes)
;                   r2 -> file image in store
;                   r3 = file image length
        STMDB   sp!,{r1-r12,lr}
        MOV     sl,sp                 ; used to remember panic exit point
        BL      do_jpeg_scan_file_16
        TEQ     pc, pc
        TEQ     pc, pc
        LDMNEIA sp!,{r1-r12,pc}^      ; 26-bit: safe
        LDMIA   sp!,{r1-r12,pc}
; Simply call this instead of cfsi_jpeg_scan_file, and subsequent calls to
; cfsi_jpeg_find_line will generate pointers to lines of 16bpp pixels, instead
; of 32bpp ones.

cfsi_jpeg_find_line
; Entry conditions: r0 -> workspace
;                   r1 = required y coordinate (in 0..image_size-1)
        STMDB   sp!,{r1-r12,lr}
        MOV     sl,sp                 ; used to remember panic exit point
        BL      jpeg_find_line
        TEQ     pc, pc
        TEQ     pc, pc
        LDMNEIA sp!,{r1-r12,pc}^      ; 26-bit: safe
        LDMIA   sp!,{r1-r12,pc}
; On exit r0 will point to the required scan line, one word per pixel, as VIDC20 RGB pixels.

cfsi_find_image_dims
; Entry conditions: r0 -> JPEG data
;                   r1 -> word in which to put image width
;                   r2 -> word in which to put image height
;                   r3 -> word in which to put image type - 1=mono, 3=YUV
;                   r4 -> word in which to put recommended size of workspace for jpeg_scan_file
; On exit, r0=0 if everything is OK, r0=1 if this data does not look
; like JPEG.
        STMDB   sp!,{r1-r12,lr}
        MOV     sl,sp                 ; used to remember panic exit point
        STMDB   sp!,{r4}              ; fifth arg to C, placed on stack
        BL      find_image_dims
        ADD     sp,sp,#4
        TEQ     pc, pc
        TEQ     pc, pc
        LDMNEIA sp!,{r1-r12,pc}^      ; 26-bit: safe
        LDMIA   sp!,{r1-r12,pc}

; Panic exit from C code. we rely on sl being preserved through
; the c code, and use it to fetch back our call registers.
; On entry here r0 has a panic code.
exit
dividebyzero
        SUBS    sp,sl,#0              ; sp := sl, set C for next instruction!
        TEQ     pc,pc                 ; sets Z if in 32-bit mode
        LDMNEIA sp!,{r1-r12,pc}^      ; 26-bit: safe
        LDMIA   sp!,{r1-r12,pc}

; Hope the asserts are OK!
newline
assert
        MOV     pc,lr

; now the actual included stuff
        GBLL    cfsi_jpeg
cfsi_jpeg SETL  {TRUE}

        GET     sources.jdhuff
        GET     sources.jrevdct
        GET     sources.jcconv
        GET     sources.diffuse
        GET     rojpeg.s

        END