/*
 * grey_8bpp.c
 * Copyright (C) 2002 P.Everett <peter@everett9981.freeserve.co.uk>
 *
 * This file is part of KinoAMP, a free RISCOS MPEG program stream decoder.
 *
 * KinoAMP is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * KinoAMP is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/*
 * This file contains the Y and YUV420 output functions for 8bpp modes.
 */

#include <string.h>
#include "inttypes.h"
#include "ka_drawers.h"

/**
 * Converts an Y source into a destination with 256 greys, 400% zoom.
 *
 * @param  paint  draw parameters
 */
void ka_drawy_z4_grey(const ka_paint_t* paint)
{
  int height;
  uint32_t *dst1, *dst2, *dst3, *dst4;
  uint32_t *y;
  int dst_skip, yc_skip;
  int i;
  uint8_t *ct = ka_Yc0_Table_8bit;


  height = paint->yc_height;
  dst1 = (uint32_t*) paint->dst;               // 1 row screen address
  dst2 = dst1 + paint->dst_bpr/4;              // 2 row screen address
  dst3 = dst2 + paint->dst_bpr/4;              // 3 row screen address
  dst4 = dst3 + paint->dst_bpr/4;              // 4 row screen address

  y = (uint32_t*) paint->base.y;               // row luminance address

  dst_skip = (3*paint->dst_bpr + paint->dst_skip) >> 2;
  yc_skip = paint->yc_skip >> 2;

  do
  {
    i = paint->yc_width >> 2;
    do
    {
      uint32_t yyyy, row1, row2, row3, row4;

      yyyy = *y++;

      row1 = ct[yyyy & 0xff];
      row2 = ct[(yyyy & 0xff00) >> 8];
      row3 = ct[(yyyy & 0xff0000) >> 16];
      row4 = ct[yyyy >> 24];
      row1 |= row1<<16;
      row2 |= row2<<16;
      row3 |= row3<<16;
      row4 |= row4<<16;
      row1 |= row1<<8;
      row2 |= row2<<8;
      row3 |= row3<<8;
      row4 |= row4<<8;
      *dst1++ = row1;
      *dst1++ = row2;
      *dst1++ = row3;
      *dst1++ = row4;
      *dst2++ = row1;
      *dst2++ = row2;
      *dst2++ = row3;
      *dst2++ = row4;
      *dst3++ = row1;
      *dst3++ = row2;
      *dst3++ = row3;
      *dst3++ = row4;
      *dst4++ = row1;
      *dst4++ = row2;
      *dst4++ = row3;
      *dst4++ = row4;
    }
    while(--i);

    y += yc_skip;
    dst1 += dst_skip;
    dst2 += dst_skip;
    dst3 += dst_skip;
    dst4 += dst_skip;
  }
  while(--height);
}

/**
 * Converts an Y source into a destination with 256 greys, 300% zoom.
 *
 * @param  paint  draw parameters
 */
void ka_drawy_z3_grey(const ka_paint_t* paint)
{
  int height;
  uint32_t *dst1, *dst2, *dst3;
  uint32_t *y;
  int dst_skip, yc_skip;
  int i;
  uint8_t *ct = ka_Yc0_Table_8bit;


  height = paint->yc_height;
  dst1 = (uint32_t*) paint->dst;               // 1 row screen address
  dst2 = dst1 + paint->dst_bpr/4;              // 2 row screen address
  dst3 = dst2 + paint->dst_bpr/4;              // 3 row screen address

  y = (uint32_t*) paint->base.y;               // row luminance address

  dst_skip = (2*paint->dst_bpr + paint->dst_skip) >> 2;
  yc_skip = paint->yc_skip >> 2;

  do
  {
    i = paint->yc_width >> 2;
    do
    {
      uint32_t yyyy, row1, row2, row3;

      yyyy = *y++;

      row1 = ct[yyyy & 0xff];
      row2 = ct[(yyyy & 0xff00) >> 8];
      row3 = ct[(yyyy & 0xff0000) >> 16];
      row1 |= (row1<<8) | (row1<<16) | (row2<<24);
      row2 |= (row2<<8) | (row3<<16) | (row3<<24);
      row3 |= ct[yyyy >> 24]<<24;
      row3 |= (row3>>8) | (row3>>16);
      *dst1++ = row1;
      *dst1++ = row2;
      *dst1++ = row3;
      *dst2++ = row1;
      *dst2++ = row2;
      *dst2++ = row3;
      *dst3++ = row1;
      *dst3++ = row2;
      *dst3++ = row3;
    }
    while(--i);

    y += yc_skip;
    dst1 += dst_skip;
    dst2 += dst_skip;
    dst3 += dst_skip;
  }
  while(--height);
}

/**
 * Converts an Y source into a destination with 256 greys, 200% zoom.
 *
 * @param  paint  draw parameters
 */
void ka_drawy_z2_grey(const ka_paint_t* paint)
{
  int height;
  uint32_t *dst1, *dst2;
  uint32_t *y;
  int dst_skip, yc_skip;
  int i;
  uint8_t *ct = ka_Yc0_Table_8bit;


  height = paint->yc_height;
  dst1 = (uint32_t*) paint->dst;               // 1 row screen address
  dst2 = dst1 + paint->dst_bpr/4;              // 2 row screen address

  y = (uint32_t*) paint->base.y;                // row luminance address

  dst_skip = (paint->dst_bpr + paint->dst_skip) >> 2;
  yc_skip = paint->yc_skip >> 2;

  do
  {
    i = paint->yc_width >> 2;
    do
    {
      uint32_t yyyy, row1, row2;

      yyyy = *y++;

      row1 = ct[yyyy & 0xff];
      row2 = ct[(yyyy & 0xff0000) >> 16];
      row1 |= ct[(yyyy & 0xff00) >> 8]<<16;
      row2 |= ct[yyyy >> 24]<<16;
      row1 |= row1<<8;
      row2 |= row2<<8;
      *dst1++ = row1;
      *dst1++ = row2;
      *dst2++ = row1;
      *dst2++ = row2;
    }
    while(--i);

    y += yc_skip;
    dst1 += dst_skip;
    dst2 += dst_skip;
  }
  while(--height);
}

/**
 * Converts an Y source into a destination with 256 greys, 100% zoom.
 *
 * @param  paint  draw parameters
 */
void ka_drawy_z1_grey(const ka_paint_t* paint)
{
  int height;
  uint32_t *dst, *y;
  uint8_t *ct = ka_Yc0_Table_8bit;
  int i;
  int dst_skip, yc_skip;


  height = paint->yc_height;
  dst = (uint32_t*) paint->dst;                // start screen address
  y = (uint32_t*) paint->base.y;               // row luminance address

  dst_skip = paint->dst_skip >> 2;
  yc_skip = paint->yc_skip >> 2;

  do
  {
    i = paint->yc_width >> 2;

    do
    {
      uint32_t yyyy, row;

      yyyy = *y++;

      row = ct[yyyy & 0xff];
      row |= ct[(yyyy & 0xff00) >> 8]<<8;
      row |= ct[(yyyy & 0xff0000) >> 16]<<16;
      row |= ct[yyyy >> 24]<<24;
      *dst++ = row;
    }
    while(--i);

    y += yc_skip;
    dst += dst_skip;
  }
  while(--height);
}

/**
 * Converts an Y source into a destination with 256 greys, 50% zoom.
 *
 * @param  paint  draw parameters
 */
void ka_drawy_z05_grey(const ka_paint_t* paint)
{
  int height;
  uint32_t *dst, *y;
  uint8_t *ct = ka_Yc0_Table_8bit;
  int i;
  int dst_skip, yc_skip;


  height = (paint->yc_height >> 1);
  dst = (uint32_t*) paint->dst;                // row screen address
  y = (uint32_t*) paint->base.y;               // row luminance address

  dst_skip = paint->dst_skip >> 2;
  yc_skip = (paint->yc_bpr + paint->yc_skip) >> 2;

  do
  {
    i = paint->yc_width >> 3;

    do
    {
      uint32_t yyyy, row;

      yyyy = *y++;
      row = ct[yyyy & 0xff];
      row |= ct[(yyyy & 0xff0000) >> 16]<<8;

      yyyy = *y++;
      row |= ct[yyyy & 0xff]<<16;
      row |= ct[(yyyy & 0xff0000) >> 16]<<24;

      *dst++ = row;
    }
    while(--i);

    y += yc_skip;
    dst += dst_skip;
  }
  while(--height);
}
