/*	
 *	framt18.c
 *
 *	P/ECE TMS9918(A) Emulator
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2005 Naoyuki Sawa
 *
 *	* Mon Jan 4 21:50:00 JST 2005 Naoyuki Sawa
 *	- 作成開始。
 */
#include "clip.h"

/****************************************************************************
 *
 ****************************************************************************/

#ifndef TMS9918_ASM

#ifdef TMS9918_GRAYSCALE
void
tms9918_reduce(unsigned char dst[/*128*88*/], const unsigned char src[/*256*192*/])
{
	const unsigned short* tmp = (const unsigned short*)src;
	//
	int c;
	int x;
	int y;
	int z;

	/* 転送元192ラインを24ラインづつ、8ブロックに分けて処理します。 */
	z = 192 / 24;
	do {
		/* 転送元24ラインを転送先11ラインに圧縮します。 */
		y = 24 / 2 - 1;
		do {
			/* y=11: 転送元ライン 0+ 1    => 転送先ライン 0
			 * y=10: 転送元ライン 2+ 3    => 転送先ライン 1
			 * y= 9: 転送元ライン 4+ 5    => 転送先ライン 2
			 * y= 8: 転送元ライン 6+ 7+ 8 => 転送先ライン 3
			 * y= 7: 転送元ライン 9+10    => 転送先ライン 4
			 * y= 6: 転送元ライン11+12    => 転送先ライン 5
			 * y= 5: 転送元ライン13+14    => 転送先ライン 6
			 * y= 4: 転送元ライン15+16+17 => 転送先ライン 7
			 * y= 3: 転送元ライン18+19    => 転送先ライン 8
			 * y= 2: 転送元ライン20+21    => 転送先ライン 9
			 * y= 1: 転送元ライン22+23    => 転送先ライン10
			 */
			x = 256 / 2;
			switch(y) {
			case 4:
			case 8:
				/* 2x3ピクセルの平均を求めます。 */
				do {
					/* c[ 7-0] = (0,0)+(0,1)+(0,2) */
					/* c[15-8] = (1,0)+(1,1)+(1,2) */
					c = tmp[0] + tmp[256 / 2] + tmp[512 / 2];
					/* c = (0,0)+(1,0)+(0,1)+(1,1)+(0,2)+(1,2) */
					c = (c & 0xff) + (c >> 8);
					*dst++ = tms9918_div6_table[c]; /* 6ピクセル平均 */
					tmp++;
				} while(--x);
				tmp += (256 * (3 - 1)) / 2; /* 3ライン下へ */
				break;
			default:
				/* 2x2ピクセルの平均を求めます。 */
				do {
					/* c[ 7-0] = (0,0)+(0,1) */
					/* c[15-8] = (1,0)+(1,1) */
					c = tmp[0] + tmp[256 / 2];
					/* c = (0,0)+(1,0)+(0,1)+(1,1) */
					c = (c & 0xff) + (c >> 8);
					*dst++ = c / 4; /* 4ピクセル平均 */
					tmp++;
				} while(--x);
				tmp += (256 * (2 - 1)) / 2; /* 2ライン下へ */
				break;
			}
		} while(--y);
	} while(--z);
}
#endif /*TMS9918_GRAYSCALE*/

void
tms9918_update_graphics2(TMS9918* tms9918, unsigned char vbuff[/*256 * 192*/])
{
	unsigned char* reg  = tms9918->reg;
	unsigned char* vram = tms9918->vram;
	//
	int backdrop;
	int block;
	int row;
	int col;
	int code;
	int line;
	int c0;
	int c1;
	int v;
	const unsigned char* name_table;
	const unsigned char* color_table;
	const unsigned char* pattern_generator;
	const unsigned char* pattern;
	const unsigned char* color;

	/* テーブルアドレスを取得します。 */
	name_table        = &vram[(reg[2] & 0x0f) << 10]; /* 1KB境界に整列 */
	color_table       = &vram[(reg[3] & 0x80) <<  6]; /* 8KB境界に整列 */
	pattern_generator = &vram[(reg[4] & 0x04) << 11]; /* 8KB境界に整列 */

	/* バックドロップカラーを取得します。 */
	backdrop = reg[7] & 0x0f;

	/* 256x192を256x64づつ、3ブロックに分けて処理します。
	 * パターンジェネレータとカラーテーブルは、ブロック毎に一つ対応します。
	 */
	for(block = 0; block < 3; block++) {

		/* 1ブロック、256x64ピクセル＝32x8セルについて... */
		for(row = 0; row < 8; row++) {
			for(col = 0; col < 32; col++) {

				/* パターン番号を取得します。 */
				code = *name_table++;

				/* パターンデータ、カラーデータの先頭アドレスを求めます。 */
				pattern = pattern_generator + code * 8;
				color = color_table + code * 8;

				/* 1セル8ラインについて... */
				for(line = 0; line < 8; line++) {

					/* パターンデータの0および1に対応するカラーを取得します。 */
					c1 = *color++;
					c0 = c1 & 0xf;
					c1 >>= 4;

					/* カラーコードが0ならば、バックドロップカラーを使います。 */
					if(!c0) c0 = backdrop;
					if(!c1) c1 = backdrop;

#ifdef TMS9918_GRAYSCALE
					/* グレイスケール時は、カラーをグレイスケールに変換します。 */
					c0 = tms9918_grayscale_table[c0];
					c1 = tms9918_grayscale_table[c1];
#endif /*TMS9918_GRAYSCALE*/

					/* パターンデータを取得します。 */
					v = *pattern++;

					/* パターンを描きます。 */
					if(v & 0x80) { *vbuff++ = c1; } else { *vbuff++ = c0; }
					if(v & 0x40) { *vbuff++ = c1; } else { *vbuff++ = c0; }
					if(v & 0x20) { *vbuff++ = c1; } else { *vbuff++ = c0; }
					if(v & 0x10) { *vbuff++ = c1; } else { *vbuff++ = c0; }
					if(v & 0x08) { *vbuff++ = c1; } else { *vbuff++ = c0; }
					if(v & 0x04) { *vbuff++ = c1; } else { *vbuff++ = c0; }
					if(v & 0x02) { *vbuff++ = c1; } else { *vbuff++ = c0; }
					if(v & 0x01) { *vbuff++ = c1; } else { *vbuff++ = c0; }

					/* 次のラインへ進めます。 */
					vbuff += 256 - 8;
				}

				/* 次のセルへ進めます。 */
				vbuff -= 256 * 8 - 8;
			}

			/* 左端の下のセルへ進めます。 */
			vbuff += 256 * 8 - 256;
		}

		/* パターンジェネレータ、カラーテーブルを次のブロックへ進めます。 */
		pattern_generator += 0x800;
		color_table += 0x800;
	}
}

#define TMS9918_SPRITE_IMPLEMENT
void tms9918_update_sprite10(TMS9918* tms9918, unsigned char vbuff[/*256 * 192*/]) {
#define SIZE 16 /* 16x16 */
#define MAG   1 /* 標準  */
#include "clipt18i.h"
#undef SIZE
#undef MAG
}
#undef TMS9918_SPRITE_IMPLEMENT

#endif /*TMS9918_ASM*/
