;********************************************************************
;
;	add_block
;
;	1.0 - 30.7.98 (bifat)	written in assembler, loops unrolled
;
;********************************************************************

		section text

		XDEF	_Add_Block
		XDEF	_Clear_Block

		XREF	_picture_structure		; int
		XREF	_current_frame			; unsigned char * [3];
		XREF	_Coded_Picture_Width		; int
		XREF	_chroma_format			; int
		XREF	_Chroma_Width			; int
		XREF	_ld				; struct layerdata *
		XREF	_Clip				; char[1024]

FRAME_PICTURE 	EQU	3
CHROMA420 	EQU	1
CHROMA422 	EQU	2
CHROMA444 	EQU	3

;********************************************************************

		cnop	0,4

_Add_Block:

		movem.l	d2-d7/a2-a6,-(a7)

		;	d0 int comp
		;	d1 int bx
		;	d2 int by
		;	d3 int dct_type
		;	d4 int addflag

		lea	_current_frame,a6


;  /* derive color component index */
;  /* equivalent to ISO/IEC 13818-2 Table 7-1 */
;  cc = (comp<4) ? 0 : (comp&1)+1; /* color component index */


		moveq	#1,d5
		and.l	d0,d5
		addq.l	#1,d5
		
		cmp.w	#4,d0
		bge	.cc_is_not_0
		moveq	#0,d5



.cc_is_0
		cmp.w	#FRAME_PICTURE,_picture_structure+2
		bne.b	.cc0notfp

		tst.w	d3
		beq.b	.notdcttype


;        /* field DCT coding */
;        rfp = current_frame[0]
;              + Coded_Picture_Width*(by+((comp&2)>>1)) + bx + ((comp&1)<<3);
;        iincr = (Coded_Picture_Width<<1) - 8;
		
		move.l	_Coded_Picture_Width,d6

		move.l	(a6),a0			; currentframe
		moveq	#2,d5
		and.l	d0,d5			; comp&2
		asr.l	#1,d5			; >> 1
		add.l	d2,d5			; +by
		muls.l	d6,d5			; * codedpicturewidth
		add.l	d5,a0			
		add.l	d1,a0			; +bx
		moveq	#1,d5
		and.l	d0,d5			; comp&1
		asl.l	#3,d5
		add.l	d5,a0 			; -> rfp
		asl.l	#1,d6
		subq.l	#8,d6			; iincr
		bra	.cont


.notdcttype

;        /* frame DCT coding */
;        rfp = current_frame[0]
;              + Coded_Picture_Width*(by+((comp&2)<<2)) + bx + ((comp&1)<<3);
;        iincr = Coded_Picture_Width - 8;

		move.l	_Coded_Picture_Width,d6
		
		move.l	(a6),a0			; currentframe
		moveq	#2,d5
		and.l	d0,d5			; comp&2
		asl.l	#2,d5			; <<2
		add.l	d2,d5			; +by
		muls.l	d6,d5			; *codedpicturewidth
		add.l	d5,a0
		add.l	d1,a0			; +bx
		moveq	#1,d5
		and.l	d0,d5			; comp&1
		asl.l	#3,d5
		add.l	d5,a0			; -> rfp
		subq.l	#8,d6			; iincr		
		bra	.cont



.cc0notfp

;      /* field picture */
;      rfp = current_frame[0]
;            + (Coded_Picture_Width<<1)*(by+((comp&2)<<2)) + bx + ((comp&1)<<3);
;      iincr = (Coded_Picture_Width<<1) - 8;

		move.l	_Coded_Picture_Width,d6
		add.l	d6,d6
		
		move.l	(a6),a0			; currentframe
		moveq	#2,d5
		and.l	d0,d5			; comp&2
		asl.l	#2,d5			; <<2
		add.l	d2,d5			; +by
		muls.l	d6,d5			; *codedpicturewidth
		add.l	d5,a0
		add.l	d1,a0			; +bx
		moveq	#1,d5
		and.l	d0,d5			; comp&1
		asl.l	#3,d5			; <<3
		add.l	d5,a0			; -> rfp
		subq.l	#8,d6			; -> iincr
		bra	.cont


.cc_is_not_0

;    /* chrominance */
;
;    /* scale coordinates */
;    if (chroma_format!=CHROMA444)
;      bx >>= 1;
;    if (chroma_format==CHROMA420)
;      by >>= 1;

		move.w	_chroma_format+2,d7
		cmp.w	#CHROMA444,d7
		beq.b	.noc1
		asr.l	#1,d1
.noc1		cmp.w	#CHROMA420,d7
		bne.b	.noc2
		asr.l	#1,d2
.noc2


;    if (picture_structure==FRAME_PICTURE)
;    {
		cmp.w	#FRAME_PICTURE,_picture_structure+2
		bne.b	.ccnot0fp

;      if (dct_type && (chroma_format!=CHROMA420))
;      {

		tst.w	d3
		beq.b	.ccnot0notdct
		cmp.w	#CHROMA420,d7
		beq.b	.ccnot0notdct


;        /* field DCT coding */
;        rfp = current_frame[cc]
;              + Chroma_Width*(by+((comp&2)>>1)) + bx + (comp&8);
;        iincr = (Chroma_Width<<1) - 8;

		move.l	_Chroma_Width,d6

		move.l	(a6,d5.w*4),a0		; currentframe[cc]
		moveq	#2,d5
		and.l	d0,d5			; comp&2
		asr.l	#1,d5			; >>1
		add.l	d2,d5			; +by
		muls.l	d6,d5			; *chromawidth
		add.l	d5,a0
		add.l	d1,a0			; +bx
		moveq	#8,d5
		and.l	d0,d5			; comp&8
		add.l	d5,a0
		add.l	d6,d6
		subq.l	#8,d6			; (chromawidth<<1)-8
		bra.b	.cont


.ccnot0notdct

;        /* frame DCT coding */
;        rfp = current_frame[cc]
;              + Chroma_Width*(by+((comp&2)<<2)) + bx + (comp&8);
;        iincr = Chroma_Width - 8;


		move.l	_Chroma_Width,d6
		
		move.l	(a6,d5.w*4),a0		; currentframe[cc]
		moveq	#2,d5
		and.l	d0,d5			; comp&2
		asl.l	#2,d5			; <<2
		add.l	d2,d5			; +by
		muls.l	d6,d5			; *chromawidth
		add.l	d5,a0
		add.l	d1,a0			; +bx
		moveq	#8,d5
		and.l	d0,d5			; comp&8
		add.l	d5,a0
		subq.l	#8,d6			; chromawidth-8
		bra.b	.cont


.ccnot0fp

;      /* field picture */
;      rfp = current_frame[cc]
;            + (Chroma_Width<<1)*(by+((comp&2)<<2)) + bx + (comp&8);
;      iincr = (Chroma_Width<<1) - 8;

		move.l	_Chroma_Width,d6
		add.l	d6,d6
		
		move.l	(a6,d5.w*4),a0		; currentframe[cc]
		moveq	#2,d5
		and.l	d0,d5			; comp&2
		asl.l	#2,d5			; <<2
		add.l	d2,d5			; +by
		muls.l	d6,d5			; *chromawidth<<1
		add.l	d5,a0
		add.l	d1,a0			; +bx
		moveq	#8,d5
		and.l	d0,d5
		add.l	d5,a0			; +comp&8
		subq.l	#8,d6			; chromawidth<<1 - 8


.cont

	;  bp = ld->block[comp];

		move.l	_ld,a1
		asl.l	#7,d0			; *128
		add.l	d0,a1


		move.l	_Clip,a2
		move.l	d6,a3
		move.w	#8,a4


		tst.l	d4
		beq.b	.noaddf


.ilop1		movem.w	(a1)+,d0-d6/a5

		moveq	#0,d7

		move.b	(a0)+,d7
		add.w	d7,d0
		move.b	(a0)+,d7
		add.w	d7,d1
		move.b	(a0)+,d7
		add.w	d7,d2
		move.b	(a0)+,d7
		add.w	d7,d3
		move.b	(a0)+,d7
		add.w	d7,d4
		move.b	(a0)+,d7
		add.w	d7,d5
		move.b	(a0)+,d7
		add.w	d7,d6
		move.b	(a0)+,d7
		add.w	a5,d7

		subq.w	#8,a0

		move.b	(a2,d0.w),(a0)+
		move.b	(a2,d1.w),(a0)+
		move.b	(a2,d2.w),(a0)+
		move.b	(a2,d3.w),(a0)+
		move.b	(a2,d4.w),(a0)+
		move.b	(a2,d5.w),(a0)+
		move.b	(a2,d6.w),(a0)+
		subq.w	#1,a4
		move.b	(a2,d7.w),(a0)+

	;	move.b	d0,(a0)+
	;	move.b	d1,(a0)+
	;	move.b	d2,(a0)+
	;	move.b	d3,(a0)+
	;	move.b	d4,(a0)+
	;	move.b	d5,(a0)+
	;	move.b	d6,(a0)+
	;	move.b	d7,(a0)+

		add.l	a3,a0
	
		move.w	a4,d0
		bne.b	.ilop1
		bra.b	.raus


		cnop	0,4
.noaddf
		add.w	#128,a2
.ilop2
		movem.w	(a1)+,d0-d7

		move.b	(a2,d0.w),(a0)+
		move.b	(a2,d1.w),(a0)+
		move.b	(a2,d2.w),(a0)+
		move.b	(a2,d3.w),(a0)+
		move.b	(a2,d4.w),(a0)+
		move.b	(a2,d5.w),(a0)+
		move.b	(a2,d6.w),(a0)+
		move.b	(a2,d7.w),(a0)+

	;	move.b	d0,
	;	move.b	d1,
	;	move.b	d2,
	;	move.b	d3,
	;	move.b	d4,
	;	move.b	d5,
	;	move.b	d6,
	;	move.b	d7,


		subq.w	#1,a4
		add.l	a3,a0
		move.w	a4,d0
		bne.b	.ilop2




.raus


		movem.l	(a7)+,d2-d7/a2-a6
		rts


;********************************************************************

		cnop	0,4

_Clear_Block:
		;	d0	blocknr

		movem.l	d2-d6,-(a7)

		move.l	_ld,a1
		asl.w	#7,d0			; *128
		add.w	d0,a1

		moveq	#0,d0
		moveq	#0,d1
		moveq	#0,d2
		moveq	#0,d3
		moveq	#0,d4
		moveq	#0,d5
		moveq	#0,d6
		move.l	d0,a0

		movem.l	d0-d6/a0,(a1)
		movem.l	d0-d6/a0,32(a1)
		movem.l	d0-d6/a0,64(a1)
		movem.l	d0-d6/a0,96(a1)

		movem.l	(a7)+,d2-d6
		rts

		END


/* IMPLEMENTATION: set scratch pad macroblock to zero */
static void Clear_Block(comp)
int comp;
{
  short *Block_Ptr;
  int i;

  Block_Ptr = ld->block[comp];

  for (i=0; i<64; i++)
    *Block_Ptr++ = 0;
}

		
;********************************************************************

/* move/add 8x8-Block from block[comp] to backward_reference_frame */
/* copy reconstructed 8x8 block from block[comp] to current_frame[]
 * ISO/IEC 13818-2 section 7.6.8: Adding prediction and coefficient data
 * This stage also embodies some of the operations implied by:
 *   - ISO/IEC 13818-2 section 7.6.7: Combining predictions
 *   - ISO/IEC 13818-2 section 6.1.3: Macroblock
*/
static void Add_Block(comp,bx,by,dct_type,addflag)
int comp,bx,by,dct_type,addflag;
{
  int cc,i, j, iincr;
  unsigned char *rfp;
  short *bp;

  
  /* derive color component index */
  /* equivalent to ISO/IEC 13818-2 Table 7-1 */
  cc = (comp<4) ? 0 : (comp&1)+1; /* color component index */

  if (cc==0)
  {
    /* luminance */

    if (picture_structure==FRAME_PICTURE)
    {
      if (dct_type)
      {
        /* field DCT coding */
        rfp = current_frame[0]
              + Coded_Picture_Width*(by+((comp&2)>>1)) + bx + ((comp&1)<<3);
        iincr = (Coded_Picture_Width<<1) - 8;
      }
      else
      {
        /* frame DCT coding */
        rfp = current_frame[0]
              + Coded_Picture_Width*(by+((comp&2)<<2)) + bx + ((comp&1)<<3);
        iincr = Coded_Picture_Width - 8;
      }
    }
    else
    {
      /* field picture */
      rfp = current_frame[0]
            + (Coded_Picture_Width<<1)*(by+((comp&2)<<2)) + bx + ((comp&1)<<3);
      iincr = (Coded_Picture_Width<<1) - 8;
    }
  }
  else
  {
    /* chrominance */

    /* scale coordinates */
    if (chroma_format!=CHROMA444)
      bx >>= 1;
    if (chroma_format==CHROMA420)
      by >>= 1;
    if (picture_structure==FRAME_PICTURE)
    {
      if (dct_type && (chroma_format!=CHROMA420))
      {
        /* field DCT coding */
        rfp = current_frame[cc]
              + Chroma_Width*(by+((comp&2)>>1)) + bx + (comp&8);
        iincr = (Chroma_Width<<1) - 8;
      }
      else
      {
        /* frame DCT coding */
        rfp = current_frame[cc]
              + Chroma_Width*(by+((comp&2)<<2)) + bx + (comp&8);
        iincr = Chroma_Width - 8;
      }
    }
    else
    {
      /* field picture */
      rfp = current_frame[cc]
            + (Chroma_Width<<1)*(by+((comp&2)<<2)) + bx + (comp&8);
      iincr = (Chroma_Width<<1) - 8;
    }
  }

  bp = ld->block[comp];

  if (addflag)
  {
    for (i=0; i<8; i++)
    {
      for (j=0; j<8; j++)
      {
        *rfp = Clip[*bp++ + *rfp];
        rfp++;
      }

      rfp+= iincr;
    }
  }
  else
  {
    for (i=0; i<8; i++)
    {
      for (j=0; j<8; j++)
        *rfp++ = Clip[*bp++ + 128];

      rfp+= iincr;
    }
  }
}
