;-------------------------------------------------------------------------;
;                                    TIGA                                 ;
;            Copyright (C) 1990  Texas Instruments Incorporated.          ;
;                            All Rights Reserved                          ;
;-------------------------------------------------------------------------;
;   TIGA 2-D Graphics Library                                             ;
;-------------------------------------------------------------------------;
;                                                                         ;
;  encode_rect - encode rectangle of pixel data into buffer               ;
;                                                                         ;
;-------------------------------------------------------------------------;
;  03/26/90   Original Version Written                     J.G.Littleton  ;
;  06/20/90   Clipping rect is now inclusive               JGL            ;
;  10/11/90   Bug fix - return value put in bytes          Jeffrey Ort
;-------------------------------------------------------------------------;
;  TMS340 register Definitions
        .copy   "gspreg.inc"
        .copy   "gsptypes.inc"
        .copy   "gspglobs.inc"

;  TMS340 Macro Definitions
        .mlib   "gspmac.lib"

;  Global Definitions
        .globl  _encode_rect    
;
;  Local register usage
Rwide    .set    A0              
Rtall    .set    A1              
Rposn    .set    A2
Rbuf     .set    A3      
Rsiz     .set    A4
Rprolog  .set    A5
Rpix     .set    A6
Rabsaddr .set    A7              
Rtmp     .set    A9
Rlpix    .set    A10            ;logical pixel multiplier
Rminrep  .set    A11
Rabscnt  .set    A12
Routsiz  .set    A13

;------------------------------------------------------------------------;
;  Header for an encoded rectangle                                       ;
;------------------------------------------------------------------------;
smMAGIC    .set   0                   ;(ushort) Magic number  
smLENGTH   .set   010h                ;(ulong)  Length of data in bytes  
smSCHEME   .set   030h                ;(ushort) Encoding scheme
smWIDTH    .set   040h                ;(short)  Width of encoded rect
smHEIGHT   .set   050h                ;(short)  Height of encoded rect
smPSIZE    .set   060h                ;(short)  Pixel size of encoded rect
smFLAGS    .set   070h                ;(ushort) Flags
smCLIPADJ  .set   080h                ;(ulong)  Y:X clip adjustment
smDATA     .set   0A0h                ;data starts here
HDRSIZ     .set   20                  ;header size in bytes
MAGIC      .set   08101h              ;Encode rect hdr magic number

GSP_34010  .set   1
GSP_34020  .set   0
ZBIT       .set   20000000h
MPTCH      .set   B11
MADDR      .set   B10

fpix10  $MACRO
r_fpix:
        move    *MADDR+,B12,0
        xor     COLOR0,B12
        dsjeq   MPTCH,r_fpix
        $END

;------------------------------------------------------------------------;
;  encode_rect( wt, ht, x, y, buf, bufsiz, options)                      ;
;------------------------------------------------------------------------;
_encode_rect:
        mmtm    SP,A0,A1,A2,A3,A4,A5,A6,A7,A9,A10,A11,A12,A13
        mmtm    SP,B7,B8,B10,B11,B12,B14
        setf    16,0,0                  
        Popc    Rwide                  ;pop Width
        Popc    Rtall                  ;pop Height
        Popc    Rposn                  ;pop X start
        Popc    A8                     ;pop Y start
        sll     16,A8
        movy    A8,Rposn               ;merge into Y:X
        Popc    Rbuf                   ;Pop buffer address
        Popc    Rsiz                   ;Pop buffer size (bytes)
        sll     3,Rsiz                 ;make it bits
        Popc    Rtmp                   ;Pop requested encoding scheme
        move    @(_env+ENVIRONMENT_DSTBM),A8,1  
        jrnz    err_encode_rect        ; exit if memory bitmap...
        move    @_env+ENVIRONMENT_XYORIGIN,A8,1   
        addxy   A8,Rposn
        move    Rtmp,Rtmp               
        jrnz    err_encode_rect
;------------------------------------------------------------------------;
;  Every encoded line of the bitmap starts with 8 bits of prologue info. ;
;  Bits 0-2 indicate size of repeating data (0=1,1=2,2=4,3=8,4=16,5=32)  ;
;  Bits 3-7 indicate data size of run lengths (1-32 signed integer)      ;
;------------------------------------------------------------------------;
        move    @PSIZE,Rpix,0        ;get Pixel size
        lmo     Rpix,A8              ;(turn pixel size  
        neg     A8                   ;  
        addk    31,A8                ;into a table index)
        move    A8,Rlpix
        move    A8,Rprolog           ;Bits 0-2 indicate repeating PSIZE
;
        lmo     Rwide,A8
        neg     A8
        addi    32+1,A8
        move    A8,Rtmp
        sll     3,Rtmp
        or      Rtmp,Rprolog         ;Bits 3-7 indicate opcode size
;------------------------------------------------------------------------;
;  Calculate the minimum number of repeating pixels required to break    ;
;  even compression wise.                                                ;
;  minrep = (opsize+(PSIZE-1)/PSIZE)+1                                   ;
;------------------------------------------------------------------------;
        add     Rpix,A8
        subk    1,A8
        move    Rpix,Rtmp
        Divl    Rtmp,A8
        addk    1,A8
        move    A8,Rminrep
;------------------------------------------------------------------------;
;  Adjust size of rectangle to be encoded to fit within the clipping     ;
;  rectangle.                                                            ;
;------------------------------------------------------------------------;
        clr     Rtmp                 ;this will be our Y:X adjust   
        move    Rposn,DADDR
        move    Rwide,DYDX
        move    Rtall,B10
        sll     16,B10
        movy    B10,DYDX
;  Clip DADDR,DYDX to WSTART,WEND
        move    DADDR,B10     
        subxy   WSTART,B10
        jrxgt   x1inside
        zext    B10,0
        addxy   B10,DYDX             ;adjust DX down
        jrxle   err_encode_rect
        subxy   B10,DADDR            ;adjust X to WSTARTX
        sext    B10,0
        neg     B10
        move    B10,Rtmp             ;save X1 adjust
        zext    Rtmp,0
x1inside:
        move    DADDR,B10
        subxy   WSTART,B10
        jrygt   y1inside
        srl     16,B10
        sll     16,B10               ;Kill X half of result
        addxy   B10,DYDX             ;adjust DY down
        jryle   err_encode_rect
        subxy   B10,DADDR            ;adjust Y to WSTARTY
        neg     B10
        move    B10,A8
        movy    A8,Rtmp
y1inside:
        move    DADDR,B10
        addxy   DYDX,B10
        move    WEND,B11
        movi    [1,1],B12
        addxy   B12,B11
        subxy   B10,B11
        jrxgt   x2inside
        zext    B11,0
        addxy   B11,DYDX
        jrxle   err_encode_rect
x2inside:
        move    DADDR,B10
        addxy   DYDX,B10
        move    WEND,B11
        addxy   B12,B11              
        subxy   B10,B11
        jrygt   y2inside
        srl     16,B11
        sll     16,B11               ;Kill X half of result
        addxy   B11,DYDX
        jryle   err_encode_rect
y2inside:
        move    DYDX,Rwide
        zext    Rwide,0
        move    DYDX,Rtall
        srl     16,Rtall
        movi    HDRSIZ*8,Routsiz
        move    Rbuf,DADDR
        addi    smDATA,DADDR
        cmp     Routsiz,Rsiz
        jrn     noheaderbuf
        move    Rtmp,*Rbuf(smCLIPADJ),1
noheaderbuf:
        addxy   Rtmp,Rposn
;------------------------------------------------------------------------;
;  Encode the rectangle                                                  ;
;------------------------------------------------------------------------;                
        Push    Rtall                ;save rect height
        move    Rpix,A8
        exgf    A8,0                 ;set FS0 to PSIZE
        move    Rprolog,A8           ;get prolog 
        srl     3,A8                 ;isolate FS of opcode
        ori     020h,A8              ;make it sign extended
        exgf    A8,1                 ;set FS1 to Opcode Size
        cvxyl   Rposn,Rposn
er_nextrow:
        move    Rposn,SADDR 
        move    Rwide,DYDX
        callr   encode_line
        move    DPTCH,A8
        add     A8,Rposn
        dsjs    Rtall,er_nextrow
;------------------------------------------------------------------------;
;  If room, fill in the header information for the encoded rectangle     ;
;------------------------------------------------------------------------;
        setf    32,0,1
        setf    16,0,0
        Pop     Rtall                ;restore rect height
        cmp     Routsiz,Rsiz
        jrn     skipheader
;  Fill in the header info
        movi    MAGIC,A8
        move    A8,*Rbuf(smMAGIC),0
        addk    7,Routsiz            ;pad required size up to-
        srl     3,Routsiz            ;-next byte boundary   
        move    Routsiz,*Rbuf(smLENGTH),1
        clr     A8
        move    A8,*Rbuf(smSCHEME),0
        move    Rwide,*Rbuf(smWIDTH),0        
        move    Rtall,*Rbuf(smHEIGHT),0        
        move    Rpix,*Rbuf(smPSIZE),0                
        move    A8,*Rbuf(smFLAGS),0
        jruc    headerexit
skipheader: 
        addk    7,Routsiz            ;pad required size up to-
        srl     3,Routsiz            ;-next byte boundary   
headerexit:
        move    Routsiz,A8
        jruc    exit_encode_rect
err_encode_rect:
        clr     A8
exit_encode_rect:
        mmfm    SP,B7,B8,B10,B11,B12,B14
        mmfm    SP,A0,A1,A2,A3,A4,A5,A6,A7,A9,A10,A11,A12,A13
        move    *SP(32),STK,1
        rets    2

;------------------------------------------------------------------------;
;  encode_line -                                                         ;
;                                                                        ;
;   SADDR=Address of line to encode                                      ;
;   DADDR=Address of output buffer                                       ;
;    DYDX=[pixel width]                                                  ;
; Rminrep=min worthy repeating sequence                                  ;
; Routsiz=size of encoded rectangle                                      ;
;    Rsiz=size of output buffer                                          ;
;------------------------------------------------------------------------;
encode_line:
        addk    8,Routsiz
        cmp     Routsiz,Rsiz
        jrn     noprologbuf
;  Save 8 bits of line prologue. Bits 0-2 are pixel size, and bits 3-7
;  are the opcode magnitude.
        movk    8,A8                 ;add prolog size to encoded size 
        exgf    A8,0                 ;set FS0 to A8 (8 bits)
        move    Rprolog,B14          
        move    B14,*DADDR+,0        ;save Prolog info
        exgf    A8,0                 ;restore FS0 and A8
noprologbuf:
        clr     Rabscnt              ;clear absolute pixel count
        move    SADDR,Rabsaddr       ;set potential abs run start address
encode_loop:
        move    DYDX,B11             ;Set max pixels to search
        move    SADDR,MADDR          ;Set run start address   
        move    *MADDR,COLOR0,0      ;Get value to look for
        .if     GSP_34010 ; Code used if the processor is a 34010
        fpix10
        .endif
        .if     GSP_34020 ; Code used if the processor is a 34020
        fpixne                       ;q: did we find a <> pixel?
        .endif
        move    DYDX,B12             
        sub     B11,B12              ;Number of repeating pixels (1-N)  
        sub     B12,DYDX             ;reduce line length
        move    Rlpix,B14            ;alt: subk Rpix,MADDR move maddr,saddr
        move    B12,B10
        sll     B14,B10
        add     B10,SADDR
        move    Rminrep,B14          ;get min repeat sequence
        cmp     B14,B12              ;q: pixels >= minrep?
        jrge    save_run             ;y: Save repeating run
;------------------------------------------------------------------------;
;  Too few for repeat run, add them to current absolute run              ;
;------------------------------------------------------------------------;
        move    Rabscnt,B14          
        add     B12,B14              ;update abs count with new pixels
        move    B14,Rabscnt
        clr     B12
        move    DYDX,DYDX
        jrgt    encode_loop
;------------------------------------------------------------------------;
;  Save absolute and/or repeating run.                                   ;
;------------------------------------------------------------------------;        
save_run:
        move    Rabscnt,B14          ;q: is there an abs run?
        jrz     absrun_done          ;n: skip it
        move    Rprolog,A8
        srl     3,A8                 ;isolate opcode magnitude
        add     A8,Routsiz           ;add to encoded size
        move    Rabscnt,A8
        sll     Rlpix,A8
        add     A8,Routsiz           ;add (abscnt*psize) to encoded size
        cmp     Routsiz,Rsiz
        jrn     absrun_done
        neg     B14                  ;y: save abs count 
        move    B14,*DADDR+,1        ;   as negative number
        move    Rabsaddr,B14
copy_absrun:
        move    *B14+,*DADDR+,0        
        dsjs    Rabscnt,copy_absrun
absrun_done:
        move    B12,B12              ;q: is there a repeat run?
        jrz     reprun_done          ;n: skip it
        move    Rprolog,A8
        srl     3,A8                 ;isolate opcode magnitude
        add     A8,Routsiz           ;add to encoded size
        add     Rpix,Routsiz         ;add psize to encoded size
        cmp     Routsiz,Rsiz
        jrn     reprun_done
        move    B12,*DADDR+,1        ;save repeat count
        move    COLOR0,*DADDR+,0     ;save repeat value
reprun_done: 
        clr     Rabscnt
        move    SADDR,Rabsaddr
        move    DYDX,DYDX
        jrgt    encode_loop
exit_encode_line:
        rets    0
