/***   [graph.c]
*
*	グラフィック 関連		(C)ささがわ
*
*	For GNU C Compiler (GCC)   Version 1.39
*
***/

#define EGB_WORK_DEFINED
#include <graph.h>
#include <jctype.h>
#include <string.h>
#include <dos.h>
#include <mos.h>
#include "others.h"

#define GRP_BUFSIZ	4096

char	EGB_work[1536];
extern int	PAL_Black;
extern int	PAL_Button;
static int	EGB_actpage;
static char	workpar[128];
static char	work1[GRP_BUFSIZ];
static char	*workptr;

extern void	_Pixelx(void *, int, const void *);
extern void	_Pixelstr(void *, const char *, int);
extern void	_Pixelstr2(void *, const char *, const void *, int);
static void wb(char);
static void ww(short);
static void wd(long);

void EGB_int(void) {
	EGB_init(EGB_work, 1536);
	EGB_actpage = 0;
}

void EGB_actPage(int p) {
	EGB_writePage(EGB_work, p);
	EGB_actpage = p;
}

int EGB_readactPage(void) {
	return EGB_actpage;
}

void EGB_cls(int c) {
	EGB_color(EGB_work, EGB_COL_BACK, c);
	EGB_clearScreen(EGB_work);
}

void EGB_box(int x1, int y1, int x2, int y2, int c) {
	EGB_paintMode(EGB_work, 0x002);
	EGB_color(EGB_work, EGB_COL_FORE, c);
	workptr = workpar;
	ww(x1);
	ww(y1);
	ww(x2);
	ww(y2);
	EGB_rectangle(EGB_work, workpar);
}

void EGB_boxf(int x1, int y1, int x2, int y2, int c1, int c2) {
	EGB_paintMode(EGB_work, c1 != c2 ? 0x022 : 0x020);
	EGB_color(EGB_work, EGB_COL_FORE, c1);
	EGB_color(EGB_work, EGB_COL_PAINT, c2);
	workptr = workpar;
	ww(x1);
	ww(y1);
	ww(x2);
	ww(y2);
	EGB_rectangle(EGB_work, workpar);
}

void EGB_pal(int n, int g, int r, int b, int syn) {
	workptr = workpar;
	wd(1);
	wd(n);
	wb(b);
	wb(r);
	wb(g);
	wb(0);
	EGB_palette(EGB_work, syn, workpar);
}

void EGB_str(const char *str, int x, int y, int c) {
	EGB_paintMode(EGB_work, 0x002);
	EGB_color(EGB_work, EGB_COL_FORE, c);
	workptr = workpar;
	ww(x);
	ww(y);
	ww(strlen(str));
	strcpy(workptr, str);
	EGB_sjisString(EGB_work, workpar);
}

void EGB_str2(const char *str, int x, int y, int c) {
	int		i, l, l1, l2, xp;
	const char	*strp;
	
	if ((l = strlen(str)) == 0)
		return;
	l1 = GRP_BUFSIZ / 16;
	l2 = (l + l1 - 1) / l1 - 1;
	strp = str;
	xp = x;
	for (i = 0; i < l2; i++) {
		int		a;
		
		_Pixelstr(work1, strp, a = strLE(strp, l1));
		EGB_putC(1, work1, xp, y - 15, xp + a * 8 - 1, y, c);
		strp += a;
		xp += a * 8;
	}
	_Pixelstr(work1, strp, l - (strp - str));
	EGB_putC(1, work1, xp, y - 15, xp + (l - (strp - str)) * 8 - 1, y, c);
}

void EGB_str3(const char *str, int x, int y, int c1, int c2) {
	int		i, l, l1, l2, xp;
	const char	*strp;
	static int	cc1 = -1, cc2 = -1;
	static unsigned char	table[1024];
	
	if (cc1 != c1 || cc2 != c2) {
		int		i, ii;
		unsigned	d;
		
		cc1 = c1;
		cc2 = c2;
		for (d = 0, ii = 0; ii < 1024; ii += 4) {
			unsigned long	b;
			
			for (b = 0, i = 0; i < 8; i++) {
				if (d >> i & 1)
					b += cc1 << (7 - i) * 4;
				else
					b += cc2 << (7 - i) * 4;
			}
			for (i = 0; i < 4; i++)
				*(table + ii + i) = *((unsigned char *)(&b) + i);
			d++;
		}
	}
	
	if ((l = strlen(str)) == 0)
		return;
	l1 = GRP_BUFSIZ / 64;
	l2 = (l + l1 - 1) / l1 - 1;
	strp = str;
	xp = x;
	for (i = 0; i < l2; i++) {
		int		a;
		
		_Pixelstr2(work1, strp, table, a = strLE(strp, l1));
		EGB_put(1, work1, xp, y - 15, xp + a * 8 - 1, y);
		strp += a;
		xp += a * 8;
	}
	_Pixelstr2(work1, strp, table, l - (strp - str));
	EGB_put(1, work1, xp, y - 15, xp + (l - (strp - str)) * 8 - 1, y);
}

void EGB_pointset(int x, int y, int c) {
	EGB_paintMode(EGB_work, 0x002);
	EGB_color(EGB_work, EGB_COL_FORE, c);
	workptr = workpar;
	ww(1);
	ww(x);
	ww(y);
	EGB_pset(EGB_work, workpar);
}

void EGB_get(void *buf, int x1, int y1, int x2, int y2) {
	struct SREGS	sregs;
	
	workptr = workpar;
	wd((long)buf);
	segread(&sregs);
	ww(sregs.ds);
	ww(x1);
	ww(y1);
	ww(x2);
	ww(y2);
	EGB_getBlock(EGB_work, workpar);
}

void EGB_put(int clip, const void *buf, int x1, int y1, int x2, int y2) {
	struct SREGS	sregs;
	
	workptr = workpar;
	wd((long)buf);
	segread(&sregs);
	ww(sregs.ds);
	ww(x1);
	ww(y1);
	ww(x2);
	ww(y2);
	EGB_putBlock(EGB_work, clip, workpar);
}

void EGB_putC(int clip, const void *buf, int x1, int y1, int x2, int y2, int c) {
	struct SREGS	sregs;
	
	EGB_paintMode(EGB_work, 0x002);
	EGB_color(EGB_work, EGB_COL_FORE, c);
	workptr = workpar;
	wd((long)buf);
	segread(&sregs);
	ww(sregs.ds);
	ww(x1);
	ww(y1);
	ww(x2);
	ww(y2);
	EGB_putBlockColor(EGB_work, clip, workpar);
}

void EGB_line(int x1, int y1, int x2, int y2, int c) {
	EGB_paintMode(EGB_work, 0x002);
	EGB_color(EGB_work, EGB_COL_FORE, c);
	workptr = workpar;
	ww(2);
	ww(x1);
	ww(y1);
	ww(x2);
	ww(y2);
	EGB_unConnect(EGB_work, workpar);
}

void EGB_rev(int c, int x1, int y1, int x2, int y2) {
	int		i, l1, l2;
	static char	init = 1;
	static unsigned char	table[256];
	
	if (init) {
		int		x, y;
		char	table2[16];
		
		for (i = 0; i < 16; table2[i++] = -1);
		table2[PAL_Black] = 15;
		table2[15] = PAL_Black;
		table2[PAL_Button] = PAL_Button;
		table2[0] = 0;
		table2[7] = 8;
		table2[8] = 7;
		
		for (i = 0; i < 16; i++) {
			int		ii;
			
			if (table2[i] != -1)
				continue;
			
			ii = i;
			do {
				if (++ii >= 16)
					ii -= 16;
			} while (table2[ii] != -1);
			table2[i] = ii;
			table2[ii] = i;
		}
		
		for (y = 0; y < 16; y++) {
			for (x = 0; x < 16; x++)
				table[(y << 4) + x] = (table2[y] << 4) + table2[x];
		}
		
		init = 0;
	}
	
	if (c)	MOS_disp(0);
	
	l1 = GRP_BUFSIZ / ((x2 - x1 + 8) / 8 * 4);
	l2 = (y2 - y1 + l1) / l1;
	for (i = 0; i < l2 - 1; i++) {
		EGB_get(work1, x1, y1 + i * l1, x2, y1 + (i + 1) * l1 - 1);
		_Pixelx(work1, (x2 - x1 + 8) / 8 * 4 * l1, table);
		EGB_put(1, work1, x1, y1 + i * l1, x2, y1 + (i + 1) * l1 - 1);
	}
	EGB_get(work1, x1, y1 + i * l1, x2, y2);
	_Pixelx(work1, (x2 - x1 + 8) / 8 * 4 * ((y2 - y1 + 1) - l1 * (l2 - 1)), table);
	EGB_put(1, work1, x1, y1 + i * l1, x2, y2);
	
	if (c)	MOS_disp(1);
}

void EGB_scrl(int m, int x1, int y1, int x2, int y2, int wx, int wy) {
	workptr = workpar;
	ww(x1);
	ww(y1);
	ww(x2);
	ww(y2);
	EGB_partScroll(EGB_work, m, wx, wy, workpar);
}

void EGB_mycopy(int p1, int x1, int y1, int x2, int y2, int p2, int x, int y) {
	int		i, l1, l2, p;
	
	p = EGB_actpage;
	l1 = GRP_BUFSIZ / ((x2 - x1 + 8) / 8 * 4);
	l2 = (y2 - y1 + l1) / l1;
	for (i = 0; i < l2 - 1; i++) {
		EGB_actPage(p1);
		EGB_get(work1, x1, y1 + i * l1, x2, y1 + (i + 1) * l1 - 1);
		EGB_actPage(p2);
		EGB_put(0, work1, x, y + i * l1, x + (x2 - x1), y + (i + 1) * l1 - 1);
	}
	EGB_actPage(p1);
	EGB_get(work1, x1, y1 + i * l1, x2, y2);
	EGB_actPage(p2);
	EGB_put(0, work1, x, y + i * l1, x + (x2 - x1), y + y2 - y1);
	EGB_actPage(p);
}

void EGB_view(int x1, int y1, int x2, int y2) {
	workptr = workpar;
	ww(x1);
	ww(y1);
	ww(x2);
	ww(y2);
	EGB_viewport(EGB_work, workpar);
}

void EGB_Hscrl(int a, int b) {
	EGB_displayStart(EGB_work, EGB_DSP_SHIFT, a, b);
}

static void wb(char b) {
	*(workptr++) = b;
}

static void ww(short w) {
	*(workptr++) = *((char *)&w);
	*(workptr++) = *((char *)&w + 1);
}

static void wd(long d) {
	*(workptr++) = *((char *)&d);
	*(workptr++) = *((char *)&d + 1);
	*(workptr++) = *((char *)&d + 2);
	*(workptr++) = *((char *)&d + 3);
}
