/* 

		○グラフィック処理関係○

		3/17 デスクトップにアイコンの表示 by is2os
		3/18 set_system32icon関数と
			 drawicon_sheet関数を追加 by is2os
		3/19 右下に「スタート」の表示 by is2os
			 
*/

#include "bootpack.h"
#include "../pictlib.h"
#include <stdio.h>
#include <string.h>

void init_palette(void)
{
	static unsigned char table_rgb[16 * 3] = {
		0x00, 0x00, 0x00,	/*  0:黒 */
		0xff, 0x00, 0x00,	/*  1:明るい赤 */
		0x00, 0xff, 0x00,	/*  2:明るい緑 */
		0xff, 0xff, 0x00,	/*  3:明るい黄色 */
		0x00, 0x00, 0xff,	/*  4:明るい青 */
		0xff, 0x00, 0xff,	/*  5:明るい紫 */
		0x00, 0xff, 0xff,	/*  6:明るい水色 */
		0xff, 0xff, 0xff,	/*  7:白 */
		0xc6, 0xc6, 0xc6,	/*  8:明るい灰色 */
		0x84, 0x00, 0x00,	/*  9:暗い赤 */
		0x00, 0x84, 0x00,	/* 10:暗い緑 */
		0x84, 0x84, 0x00,	/* 11:暗い黄色 */
		0x00, 0x00, 0x84,	/* 12:暗い青 */
		0x84, 0x00, 0x84,	/* 13:暗い紫 */
		0x00, 0x84, 0x84,	/* 14:暗い水色 */
		0x84, 0x84, 0x84	/* 15:暗い灰色 */
	};
	unsigned char table2[216 * 3];
	int r, g, b;
	set_palette(0, 15, table_rgb);
	for (b = 0; b < 6; b++) {
		for (g = 0; g < 6; g++) {
			for (r = 0; r < 6; r++) {
				table2[(r + g * 6 + b * 36) * 3 + 0] = r * 51;
				table2[(r + g * 6 + b * 36) * 3 + 1] = g * 51;
				table2[(r + g * 6 + b * 36) * 3 + 2] = b * 51;
			}
		}
	}
	set_palette(16, 231, table2);
	return;
}

void set_palette(int start, int end, unsigned char *rgb)
{
	int i, eflags;
	eflags = io_load_eflags();	/* 割り込み許可フラグの値を記録する */
	io_cli(); 					/* 許可フラグを0にして割り込み禁止にする */
	io_out8(0x03c8, start);
	for (i = start; i <= end; i++) {
		io_out8(0x03c9, rgb[0] / 4);
		io_out8(0x03c9, rgb[1] / 4);
		io_out8(0x03c9, rgb[2] / 4);
		rgb += 3;
	}
	io_store_eflags(eflags);	/* 割り込み許可フラグを元に戻す */
	return;
}

void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1)
{
	int x, y;
	for (y = y0; y <= y1; y++) {
		for (x = x0; x <= x1; x++)
			vram[y * xsize + x] = c;
	}
	return;
}

void start_screen(char *vram, struct BOOTINFO *binfo, int *fat, char *logoname)
{
	struct MEMMAN *memman = (struct MEMMAN *)MEMMAN_ADDR;
	unsigned char *filebuf, r, g, b;
	struct DLL_STRPICENV env;
	struct RGB *picbuf;
	int info[4], fsize, xx, yy;
	struct FILEINFO *finfo;

	/* 起動前のメッセージ */
	boxfill8(vram, binfo->scrnx, COL8_000000, 0, 0, binfo->scrnx, binfo->scrny);
	putfonts8_asc(vram, binfo->scrnx, (int)binfo->scrnx / 2 - 26 * 4 - 1, 70, COL8_FFFFFF, "Wellcome to NegitoroOS !!");
	putfonts8_asc(vram, binfo->scrnx, (int)binfo->scrnx / 2 - 20 * 9 - 1, 100, COL8_FFFFFF, "This operating system is useful and fast!");
	putfonts8_asc(vram, binfo->scrnx, (int)binfo->scrnx / 2 - 25 * 8 - 1, 120, COL8_FFFFFF, "Maybe It is faster than other operating system!");
	putfonts8_asc(vram, binfo->scrnx, (int)binfo->scrnx / 2 - 13 * 9 - 1, 140, COL8_FFFFFF, "Let's enjoy negitoro life!!");
	putfonts8_asc(vram, binfo->scrnx, (int)binfo->scrnx / 2 - 21 * 9 - 1, 190, COL8_FFFFFF, "Copylight(c) by 2008 By I&S(nickname is 39)");
	putfonts8_asc(vram, binfo->scrnx, (int)binfo->scrnx / 2 - 10 * 10 - 1, 210, COL8_FFFFFF, "Allright reserved(r)");
	putfonts8_asc(vram, binfo->scrnx, (int)binfo->scrnx / 2 - 5 * 11 - 1, 230, COL8_FFFFFF, "Thaks all!!");
	putfonts8_asc(vram, binfo->scrnx, (int)binfo->scrnx / 2 - 16 * 4 - 1, 440, COL8_FFFFFF, "Loading now.....");

	/* 下の方にロゴを表示 */
	finfo = file_search(logoname, (struct FILEINFO *) (ADR_DISKIMG + 0x002600), 224);
	if (finfo != 0) {
		fsize   = finfo->size;
		filebuf = (unsigned char *) memman_alloc_4k(memman, fsize);
		filebuf = file_loadfile2(finfo->clustno, &fsize, fat);
		info_JPEG(&env, info, fsize, filebuf);
		picbuf  = (struct RGB *) memman_alloc_4k(memman, info[2] * info[3] * sizeof(struct RGB));
		decode0_JPEG(&env, fsize, filebuf, 4, (unsigned char *) picbuf, 0);
		for (yy = 0; yy < info[3]; yy++) {
			for (xx = 0; xx < info[2]; xx++) {
				r = picbuf[yy * info[2] + xx].r;
				g = picbuf[yy * info[2] + xx].g;
				b = picbuf[yy * info[2] + xx].b;
				vram[(info[3] + 140 + yy) * binfo->scrnx + (xx + (int)(binfo->scrnx / 2 - info[2] / 2) - 10)] = 
															(16 + (r / 43) + (g / 43) * 6 + (b / 43) * 36) & 0xff;
			}
		}
	}

	return;
}

void init_screen8(char *vram, struct BOOTINFO *binfo, int *fat, char *wallname)
{
	if (wallname == 0)
		goto no_wall;
	
	struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
	unsigned char *filebuf, r, g, b;
	struct DLL_STRPICENV env;
	struct RGB *picbuf;
	int info[4], fsize, xx, yy;
	struct FILEINFO *finfo = file_search(wallname, (struct FILEINFO *) (ADR_DISKIMG + 0x002600), 224);

	if (finfo != 0) {
		fsize   = finfo->size;
		filebuf = (unsigned char *) memman_alloc_4k(memman, fsize);
		filebuf = file_loadfile2(finfo->clustno, &fsize, fat);
		info_JPEG(&env, info, fsize, filebuf);
		picbuf  = (struct RGB *) memman_alloc_4k(memman, info[2] * info[3] * sizeof(struct RGB));
		decode0_JPEG(&env, fsize, filebuf, 4, (unsigned char *) picbuf, 0);
		for (yy = 0; yy < info[3]; yy++) {
			for (xx = 0; xx < info[2]; xx++) {
				r = picbuf[yy * info[2] + xx].r;
				g = picbuf[yy * info[2] + xx].g;
				b = picbuf[yy * info[2] + xx].b;
				vram[yy * binfo->scrnx + xx] = (16 + (r / 43) + (g / 43) * 6 + (b / 43) * 36) & 0xff;
			}
		}
	} else {
no_wall:
		boxfill8(vram, binfo->scrnx, COL8_008484, 0, 0, binfo->scrnx - 1, binfo->scrny - 1);
	}

	/* 右下の時刻表示用ボックス */
	boxfill8(vram, binfo->scrnx, COL8_848484, 80, binfo->scrny - 24, 250, binfo->scrny);
	boxfill8(vram, binfo->scrnx, COL8_C6C6C6, 81, binfo->scrny - 23, 249, binfo->scrny - 2);
	boxfill8(vram, binfo->scrnx, COL8_FFFFFF, 84, binfo->scrny - 20, 245, binfo->scrny - 5);
	
	/* スタートボタン */
	boxfill8(vram, binfo->scrnx, COL8_000000, 0, binfo->scrny - 24, 79, binfo->scrny);
	boxfill8(vram, binfo->scrnx, COL8_C6C6C6, 1, binfo->scrny - 23, 78, binfo->scrny - 2);
	putfonts8_asc(vram, binfo->scrnx, 21, binfo->scrny - 20, COL8_848484, "start");
	putfonts8_asc(vram, binfo->scrnx, 20, binfo->scrny - 21, COL8_000000, "start");
	
	return;
}

/* 指定したシートにアイコンを描写 */
int drawicon_sheet(struct SHTCTL *shtctl, char *draw_to, int pos_x, 
						int pos_y, char *icon_name, char *icon_file, int *fat, int color)
{
	char name[40];
	
	strcpy(name, icon_file);
	if (icon_file == NULL)
		strcpy(name, shtctl->icon_default);

	struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
	struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
	unsigned char *filebuf, r, g, b;
	struct DLL_STRPICENV env;
	struct RGB *picbuf;
	int info[4], fsize, xx, yy;
	struct FILEINFO *finfo;

	finfo = file_search(name, (struct FILEINFO *)(ADR_DISKIMG + 0x002600), 224);
	if (finfo != 0) {
		fsize = finfo->size;
		filebuf = (unsigned char *)memman_alloc_4k(memman, fsize);
		filebuf = file_loadfile2(finfo->clustno, &fsize, fat);
		info_BMP(&env, info, fsize, filebuf);
		picbuf = (struct RGB *)memman_alloc_4k(memman, info[2] * info[3] * sizeof(struct RGB));
		decode0_BMP(&env, fsize, filebuf, 4, (unsigned char *)picbuf, 0);
		for (yy = 0; yy < info[3]; yy++) {
			for (xx = 0; xx < info[2]; xx++) {
				r = picbuf[yy * info[2] + xx].r;
				g = picbuf[yy * info[2] + xx].g;
				b = picbuf[yy * info[2] + xx].b;
				draw_to[(yy + pos_y) * binfo->scrnx + (xx + pos_x)] = (16 + (r / 43) + (g / 43) * 6 + (b / 43) * 36) & 0xff;
			}
		}
	}
	
	putfonts8_asc(draw_to, binfo->scrnx, pos_x - (strlen(icon_name) * 8 / 2 - info[2] / 2) + 1, 
												pos_y + info[3] + 8, color, icon_name);
	return 0;
}

/* デフォルトのアイコンを設定 */
int set_system32icon(struct SHTCTL *shtctl, char *icon_name)
{
	struct FILEINFO *finfo = file_search(icon_name, (struct FILEINFO *)(ADR_DISKIMG + 0x002600), 224);
	if (finfo != 0) {
		strcpy(shtctl->icon_default, icon_name);
		return 0;
	}
	return 1;
}

void putfont8(char *vram, int xsize, int x, int y, char c, char *font)
{
	int i;
	char *p, d /* data */;
	for (i = 0; i < 16; i++) {
		p = vram + (y + i) * xsize + x;
		d = font[i];
		if ((d & 0x80) != 0) { p[0] = c; }
		if ((d & 0x40) != 0) { p[1] = c; }
		if ((d & 0x20) != 0) { p[2] = c; }
		if ((d & 0x10) != 0) { p[3] = c; }
		if ((d & 0x08) != 0) { p[4] = c; }
		if ((d & 0x04) != 0) { p[5] = c; }
		if ((d & 0x02) != 0) { p[6] = c; }
		if ((d & 0x01) != 0) { p[7] = c; }
	}
	return;
}

void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s)
{
	extern char hankaku[4096];
	struct TASK *task = task_now();
	char *nihongo = (char *) *((int *) 0x0fe8), *font;
	int k, t;

	if (task->langmode == 0) {
		for (; *s != 0x00; s++) {
			putfont8(vram, xsize, x, y, c, hankaku + *s * 16);
			x += 8;
		}
	}
	if (task->langmode == 1) {
		for (; *s != 0x00; s++) {
			if (task->langbyte1 == 0) {
				if ((0x81 <= *s && *s <= 0x9f) || (0xe0 <= *s && *s <= 0xfc)) {
					task->langbyte1 = *s;
				} else {
					putfont8(vram, xsize, x, y, c, nihongo + *s * 16);
				}
			} else {
				if (0x81 <= task->langbyte1 && task->langbyte1 <= 0x9f) {
					k = (task->langbyte1 - 0x81) * 2;
				} else {
					k = (task->langbyte1 - 0xe0) * 2 + 62;
				}
				if (0x40 <= *s && *s <= 0x7e) {
					t = *s - 0x40;
				} else if (0x80 <= *s && *s <= 0x9e) {
					t = *s - 0x80 + 63;
				} else {
					t = *s - 0x9f;
					k++;
				}
				task->langbyte1 = 0;
				font = nihongo + 256 * 16 + (k * 94 + t) * 32;
				putfont8(vram, xsize, x - 8, y, c, font     );	/* 左半分 */
				putfont8(vram, xsize, x    , y, c, font + 16);	/* 右半分 */
			}
			x += 8;
		}
	}
	if (task->langmode == 2) {
		for (; *s != 0x00; s++) {
			if (task->langbyte1 == 0) {
				if (0x81 <= *s && *s <= 0xfe) {
					task->langbyte1 = *s;
				} else {
					putfont8(vram, xsize, x, y, c, nihongo + *s * 16);
				}
			} else {
				k = task->langbyte1 - 0xa1;
				t = *s - 0xa1;
				task->langbyte1 = 0;
				font = nihongo + 256 * 16 + (k * 94 + t) * 32;
				putfont8(vram, xsize, x - 8, y, c, font     );	/* 左半分 */
				putfont8(vram, xsize, x    , y, c, font + 16);	/* 右半分 */
			}
			x += 8;
		}
	}
	return;
}

void init_mouse_cursor8(char *mouse, char bc)
/* マウスカーソルを準備（16x16） */
{
	static char cursor[16][16] = {
		"**************..",
		"*OOOOOOOOOOO*...",
		"*OOOOOOOOOO*....",
		"*OOOOOOOOO*.....",
		"*OOOOOOOO*......",
		"*OOOOOOO*.......",
		"*OOOOOOO*.......",
		"*OOOOOOOO*......",
		"*OOOO**OOO*.....",
		"*OOO*..*OOO*....",
		"*OO*....*OOO*...",
		"*O*......*OOO*..",
		"**........*OOO*.",
		"*..........*OOO*",
		"............*OO*",
		".............***"
	};
	int x, y;

	for (y = 0; y < 16; y++) {
		for (x = 0; x < 16; x++) {
			if (cursor[y][x] == '*') {
				mouse[y * 16 + x] = COL8_000000;
			}
			if (cursor[y][x] == 'O') {
				mouse[y * 16 + x] = COL8_FFFFFF;
			}
			if (cursor[y][x] == '.') {
				mouse[y * 16 + x] = bc;
			}
		}
	}
	return;
}

void putblock8_8(char *vram, int vxsize, int pxsize,
	int pysize, int px0, int py0, char *buf, int bxsize)
{
	int x, y;
	for (y = 0; y < pysize; y++) {
		for (x = 0; x < pxsize; x++) {
			vram[(py0 + y) * vxsize + (px0 + x)] = buf[y * bxsize + x];
		}
	}
	return;
}
