#help_index "Graphics/Screen"

U0 GrSetUpTables()
{
	CDC *dc;
	I64  i, j, k, l, m, x, y, rr;
	U8  *dst;

	k = 0;
	for (i = 0; i < 256; i++)
		for (j = 0; j < 8; j++)
			if (Bt(&i, j))
				gr.to_8_bits(U8 *)[k++] = 0xFF;
			else
				gr.to_8_bits(U8 *)[k++] = 0x00;
	k = 0;
	for (i = 0; i < 256; i++)
		for (j = 0; j < 8; j++)
			gr.to_8_colors(U8 *)[k++] = i;

	for (i = 0; i < GR_PEN_BRUSHES_NUM; i++)
	{
		k = i + 1;

		rr = k * k;
		for (y = 1; y < k; y++)
			for (x = 1; x < k; x++)
				if (SqrI64(y * 2 - k) + SqrI64(x * 2 - k) < rr)
				{
					if (x - 1 - i >> 1 < gr.circle_lo[i][i - y])
						gr.circle_lo[i][i - y] = x - 1 - i >> 1;
					if (x - 1 - i >> 1 > gr.circle_hi[i][i - y])
						gr.circle_hi[i][i-y] = x - 1 - i >> 1;
				}

		dc = DCNew(i, i);
		gr.pen_brushes[i] = dc;
		dc->color = COLOR_MONO;
		rr = k * k;
		for (y = 1; y < k; y++)
			for (x = 1; x < k; x++)
				if (SqrI64(y * 2 - k) + SqrI64(x * 2 - k) < rr)
					GrPlot0(dc, x - 1, y - 1);

		dc = DCNew(i, i);
		gr.collision_pen_brushes[i] = dc;
		dc->color = COLOR_INVALID;//Want color that never occurs.
		rr = k * k;
		for (y = 1; y < k; y++)
			for (x = 1; x < k; x++)
				if (SqrI64(y * 2 - k) + SqrI64(x * 2 - k) < rr)
					GrPlot0(dc, x - 1, y - 1);

		dc = DCNew(i, i);
		gr.even_pen_brushes[i] = dc;
		dc->color = COLOR_MONO;
		rr = k * k;
		for (y = 1;y < k; y++)
			for (x = 1; x < k; x++)
				if (!(((x - 1) ^ (y - 1)) & 1) && SqrI64(y * 2 - k) + SqrI64(x * 2 - k) < rr)
					GrPlot0(dc, x - 1, y - 1);

		dc = DCNew(i, i);
		gr.odd_pen_brushes[i] = dc;
		dc->color = COLOR_MONO;
		rr = k * k;
		for (y = 1; y < k; y++)
			for (x = 1; x < k; x++)
				if (((x - 1) ^ (y - 1)) & 1 && SqrI64(y * 2 - k) + SqrI64(x * 2 - k) < rr)
					GrPlot0(dc, x - 1, y - 1);
	}

	for (i = 1; i <= GR_SCREEN_ZOOM_MAX; i++)
	{
		dst = gr.screen_zoom_tables[i] = MAlloc(256 * i);
		for (j = 0; j < 256; j++)
		{
			m = 0;
			for (k = 0; k < 8; k++)
			{
				if (Bt(&j, k))
				{
					for (l = 0; l < i; l++)
						Bts(&m, l + k * i);
				}
			}
			for (l = 0; l < i; l++)
				dst[j + l * 256] = m.u8[l];
		}
	}
}

#help_index "Graphics/Screen;Windows"

U0 WinZBufFill(CTask *task)
{//Not public
	I64 y, t, b, l, r, w;
	if (!Bt(&task->display_flags, DISPLAYf_NO_BORDER))
	{
		if (task->win_top - 1 > 0)
			t = task->win_top - 1;
		else
			t = 0;
		if (task->win_bottom + 1 < TEXT_ROWS)
			b = task->win_bottom + 1;
		else
			b = TEXT_ROWS - 1;
		if (task->win_left - 1 > 0)
			l = task->win_left - 1;
		else
			l = 0;
		if (task->win_right + 1 < TEXT_COLS)
			r = task->win_right + 1;
		else
			r = TEXT_COLS - 1;
	}
	else
	{
		if (task->win_top > 0)
			t = task->win_top;
		else
			t = 0;
		if (task->win_bottom < TEXT_ROWS)
			b = task->win_bottom;
		else
			b = TEXT_ROWS - 1;
		if (task->win_left > 0)
			l = task->win_left;
		else
			l = 0;
		if (task->win_right < TEXT_COLS)
			r = task->win_right;
		else
			r = TEXT_COLS - 1;
	}
	t = ClampI64(t, 0, TEXT_ROWS - 1);
	b = ClampI64(b, t, TEXT_ROWS - 1);
	l = ClampI64(l, 0, TEXT_COLS - 1);
	r = ClampI64(r, l, TEXT_COLS - 1);
	if (w = r - l + 1)
		for (y = t; y <= b; y++)
			MemSetU16(gr.win_z_buf(U8 *) + (y * TEXT_COLS + l) * sizeof(U16), task->win_z_num, w);
}

public U0 WinZBufUpdate()
{//Might have to call if doing graphics outside winmgr callback routines.
//Call it if, for example, when a pop-up window closes and you need to refresh
	//before graphics.
	I64		 i, z = 1;
	U16		*ptr;
	CTask	*task, *task1;

	if (gr.win_z_buf)
	{
		LBtr(&sys_semas[SEMA_UPDATE_WIN_Z_BUF], 0);
		task1 = task = sys_winmgr_task;
		do
		{
			if (!TaskValidate(task))
				break;
			if (Bt(&task->display_flags, DISPLAYf_SHOW))
			{
				task->win_z_num = z++;
				WinZBufFill(task);
			}
			task = task->next_task;
		}
		while (task != task1 && z < 0x10000);

		MemSet(gr.win_uncovered_bitmap, 0, (gr.highest_uncovered + 7) >> 3 + 1);
		gr.highest_uncovered = z - 1;
		for (ptr = gr.win_z_buf, i = TEXT_ROWS * TEXT_COLS; i; i--)
			Bts(gr.win_uncovered_bitmap, *ptr++);
	}
}

#help_index "Graphics"
U0 GrInit2()
{
	MemSet(&gr, 0, sizeof(CGrGlobals));
	gr.sprite_hash = HashTableNew(512);
	HashDefineListAdd("ST_SPRITE_ELEM_CODES", SPHT_ELEM_CODE, gr.sprite_hash);
	gr.screen_zoom = 1;

	PaletteSetDark;

	gr.to_8_bits	= MAlloc(256 * sizeof(I64));
	gr.to_8_colors	= MAlloc(256 * sizeof(I64));

	gr.screen_cache = MAlloc(sys_vbe_mode.width * sys_vbe_mode.height);

	gr.text_base			= CAlloc(TEXT_ROWS * TEXT_COLS * sizeof(U32));
	gr.win_uncovered_bitmap	= CAlloc(65536 / 8);
	gr.highest_uncovered	= 0;
	gr.win_z_buf			= MAlloc(TEXT_ROWS * TEXT_COLS * sizeof(U16));

	gr.dc2 = DCNew(GR_WIDTH, GR_HEIGHT);
	gr.dc2->flags |= DCF_SCREEN_BITMAP;
	gr.dc_cache = DCNew(GR_WIDTH, GR_HEIGHT);

	gr.dc = DCNew(GR_WIDTH, GR_HEIGHT);
	gr.dc->flags |= DCF_SCREEN_BITMAP | DCF_ON_TOP;
	DCFill;

	gr.dc1 = DCNew(GR_WIDTH, GR_HEIGHT);
	gr.dc1->flags |= DCF_SCREEN_BITMAP;

	gr.screen_image	= DCNew(GR_WIDTH, GR_HEIGHT); //4-bit
	gr.zoomed_dc	= DCNew(GR_WIDTH, GR_HEIGHT); //4-bit
	gr.zoomed_dc->flags |= DCF_SCREEN_BITMAP;
}

GrInit2;
