/* "VESA8.ASK" for PC/AT ver.0.3 copyright(C) 2004 川合秀実 */

segment CODE(USE32, PARA);
default(code == CODE);

//	#define QEMU		1

struct GAPI_WORK {
	signed int mx, my, mx0, my0, mx1, my1;
	int cursor_addr, pattern_addr;
	unsigned int lockcount, mouselock; /* +32 */
	char mouseflag, maskflag, mouseline, V86flag;
//	int mouseline, masktype;
	int VGA_mode;
	short V86CS, V86SS, [4], [8];
	int backup_buf[320]; /* +64 */
	int mouse_pattern[2560 /* 0x0a00 */]; /* +0x0180 */
	int linebytes;
	void [1136];
	/* 以上4KB */
};

void far GAPI_entry()
/* 必ず、EFLAGS.IF == 1で呼ぶこと */
{
	goto syscmd;
//	ORG(0x0008);
//	ORG(0x0010);
	asmout("RESB 0x10-$");
	asmout("DD OFFSET #syscmd, 0, 0, 0");
	DD(4096); /* 初期化時に必要なワークエリアサイズ */
	DD(0); /* 最大ローカルスタック消費量 */
//	ORG(0x0040);
	asmout("RESB 0x40-$");
syscmd:
	GAPI_WORK *work == ES:0x0000;

	int all_sel == 1 * 8;
	int *cmd == FS:EBX;

	asmout("#GAPI_accesslock EQU GAPI_accesslock");
	asmout("#GAPI_mouse EQU GAPI_mouse");
	asmout("#GAPI_line EQU GAPI_line");
	asmout("#GAPI_fontwrite EQU GAPI_fontwrite");
	asmout("#GAPI_init EQU GAPI_init");
	asmout("#GAPI_resetdevice EQU GAPI_resetdevice");
	asmout("#GAPI_error EQU GAPI_error");
	asmout("#GAPI_putbox EQU GAPI_putbox");
	asmout("#GAPI_lineardots EQU GAPI_lineardots");
	asmout("#GAPI_points EQU GAPI_points");

	PUSH(DS);
	PUSH(ES);
	PUSHAD();
	PUSH(all_sel);
	POP(DS);
	MOV(ECX, CS);
	ECX += 8;
	ES = ECX;

asmout("next_command: EQU $");

	EAX = cmd[0];
	if (EAX == 0x0184)
		goto GAPI_accesslock;
	if (EAX == 0x0101)
		goto GAPI_fontwrite;
	if (EAX == 0x0108)
		goto GAPI_putbox;
	if (EAX == 0x0100)
		goto GAPI_line;
	if (EAX == 0x010c)
		goto GAPI_lineardots;
	if (EAX == 0x0110)
		goto GAPI_points;
	if (EAX == 0x0180)
		goto GAPI_mouse;
	if (EAX == 0x0010)
		goto GAPI_init;
	if (EAX == 0x001c)
		goto GAPI_resetdevice;
	if (EAX == 0x0104)
		goto fontload;
//	if (EAX == 0x0108)
//		goto allocarea; /* cmd, opt, size, (addr) */
	if (EAX == 0x0140)
		goto font_attr; /* cmd, opt, type, (param0), (param1), (param2), (param3) */

	if (EAX != 0)
		goto GAPI_error;

	[SS:ESP + 16] = EBX;
	POPAD();
	POP(ES);
	POP(DS);
	return;

fontload:
	/* cmd, opt, type, len, to, from */
	PUSH(DS);
	asmout("LDS ESI,DWORD FS:[EBX+20]");
	EAX = cmd[ 8]; /* type */
	ECX = cmd[12]; /* len */
	EDI = cmd[16]; /* to */
	(offset) cmd += 28;
	if (EAX <= 2) {
		/* mono, full/half */
		LEA(ECX, [ECX * 2]);
		if (!=)
			ECX *= 2;
		do {
			EAX = [DS:ESI];
			ESI += 4;
			[ES:EDI] = EAX;
			EDI += 4;
			ECX--;
		} while (!= 0);
		POP(DS);
		asmout("JMP next_command");
	}
	if (EAX <= 4) {
		/* EAX == 3:4bit color 8x16 */
		/* EAX == 4:4bit color 8x8 */
		LEA(ECX, [ECX * 8]);
		if (!=)
			ECX *= 2;
		do {
			EDX = [DS:ESI]; /* 8dots */
			ESI += 4;
			AH = DH;
			AL = DH;
			(unsigned char) AH >>= 4;
			EAX <<= 16;
			AH = DL;
			AL = DL;
			(unsigned char) AH >>= 4;
			EAX &= 0x0f0f0f0f;
			[ES:EDI] = EAX;
			(unsigned int) EDX >>= 16;
			AH = DH;
			AL = DH;
			(unsigned char) AH >>= 4;
			EAX <<= 16;
			AH = DL;
			AL = DL;
			(unsigned char) AH >>= 4;
			EAX &= 0x0f0f0f0f;
			[ES:EDI + 4] = EAX;
			EDI += 8;
			ECX--;
		} while (!= 0);
		POP(DS);
		asmout("JMP next_command");
	}
	INT(0x03);

font_attr:
	/* cmd, opt, type, (param0), (param1), (param2), (param3) */
	EAX = cmd[ 8]; /* type */
	asmout("MOV AL,BYTE PTR CS:[#font_attr_table+EAX-1]");
	(char) cmd[12] = AL;
	(offset) cmd += 28;
	asmout("JMP next_command");
font_attr_table:
	DB(4 /*  16bytes/font (8x16 mono) */);
	DB(3 /*   8bytes/font (8x 8 mono half height) */);
	DB(7 /* 128bytes/font (8x16 4bit color) */);
	DB(6 /*  64bytes/font (8x 8 4bit color half height) */);
}

void GAPI_fontwrite()
{
	/* 8x16のフォントを描画(背景色付き) */
	int *cmd == FS:EBX;
	GAPI_WORK *work == ES:0x0000;

	/* opt	bit0:full higth/half height
			bit1-7:	0000000 mono font col&bcol
					0000001 4bit color font
	*/

	EAX = cmd[4];
	if (AH != 0)
		goto opt_high;
	if ((unsigned) EAX >= 2)
		goto opt2;
	EAX = cmd[ 8]; /* x */
	ESI = cmd[12]; /* y */
	TEST(AL, 0x03);
	if (!= 0)
		goto error; /* 4の倍数以外はまだサポートしてない */

	IMUL(ESI, work->linebytes);
	ESI += EAX;

	int *font == ES:EDI;
	EAX = (unsigned char) cmd[20]; /* bgcolor */
	EDX = EAX;
	EAX <<= 8;
	EDX |= EAX;
	EAX = EDX;
	EDX <<= 16;
	EAX |= EDX;
	PUSH(EAX);

	EAX = (unsigned char) cmd[16]; /* color */
	EDX = EAX;
	EAX <<= 8;
	EDX |= EAX;
	EAX = EDX;
	EDX <<= 16;
	EAX |= EDX;
	POP(EDX);
	EBP = EAX;

	/* EBP:col, EDX:bgcol */
	PUSH(EBP); // 1111
	EAX = EBP; ECX = EDX; EAX &= 0x00ffffff; ECX &= 0xff000000; EAX |= ECX; PUSH(EAX); // 1110
	EAX = EBP; ECX = EDX; EAX &= 0xff00ffff; ECX &= 0x00ff0000; EAX |= ECX; PUSH(EAX); // 1101
	EAX = EBP; ECX = EDX; EAX &= 0x0000ffff; ECX &= 0xffff0000; EAX |= ECX; PUSH(EAX); // 1100
	EAX = EBP; ECX = EDX; EAX &= 0xffff00ff; ECX &= 0x0000ff00; EAX |= ECX; PUSH(EAX); // 1011
	EAX = EBP; ECX = EDX; EAX &= 0x00ff00ff; ECX &= 0xff00ff00; EAX |= ECX; PUSH(EAX); // 1010
	EAX = EBP; ECX = EDX; EAX &= 0xff0000ff; ECX &= 0x00ffff00; EAX |= ECX; PUSH(EAX); // 1001
	EAX = EBP; ECX = EDX; EAX &= 0x000000ff; ECX &= 0xffffff00; EAX |= ECX; PUSH(EAX); // 1000
	EAX = EBP; ECX = EDX; EAX &= 0xffffff00; ECX &= 0x000000ff; EAX |= ECX; PUSH(EAX); // 0111
	EAX = EBP; ECX = EDX; EAX &= 0x00ffff00; ECX &= 0xff0000ff; EAX |= ECX; PUSH(EAX); // 0110
	EAX = EBP; ECX = EDX; EAX &= 0xff00ff00; ECX &= 0x00ff00ff; EAX |= ECX; PUSH(EAX); // 0101
	EAX = EBP; ECX = EDX; EAX &= 0x0000ff00; ECX &= 0xffff00ff; EAX |= ECX; PUSH(EAX); // 0100
	EAX = EBP; ECX = EDX; EAX &= 0xffff0000; ECX &= 0x0000ffff; EAX |= ECX; PUSH(EAX); // 0011
	EAX = EBP; ECX = EDX; EAX &= 0x00ff0000; ECX &= 0xff00ffff; EAX |= ECX; PUSH(EAX); // 0010
	EAX = EBP; ECX = EDX; EAX &= 0xff000000; ECX &= 0x00ffffff; EAX |= ECX; PUSH(EAX); // 0001
	PUSH(EDX); // 0000

//	ES = [FS:EBX + 28];
	/* fontsizeチェックはしなくなった。その方が速い。
	   チェックが必要なら、上位ルーチンでやる。 */

	int *string == FS:EBP;
	ECX = cmd[32]; // length

	if (cmd[4] != 0)
		goto opt1;

	LEA((offset) string, [EBX + 36]);
//	LEA(EBX, [EBX + ECX * 4 + 36]);

	do {
		PUSH(ECX);
		(offset) font = *string;
		(offset) string += 4;
		ECX = 4;
		do {
			EBX = *font; /* 4lines */
			(offset) font += 4;
			EDX = EBX;
			(unsigned int) EBX /= 16;
			EDX &= 0x0f;
			EAX = [SS:ESP + EDX * 4 + 4];
			EDX = EBX;
			(unsigned int) EBX /= 16;
			EDX &= 0x0f;
			[DS:ESI + 0xe0000000 + 4] = EAX;

			EAX = [SS:ESP + EDX * 4 + 4];
			EDX = EBX;
			(unsigned int) EBX /= 16;
			EDX &= 0x0f;
			[DS:ESI + 0xe0000000 + 0] = EAX;
			ESI += work->linebytes;

			EAX = [SS:ESP + EDX * 4 + 4];
			EDX = EBX;
			(unsigned int) EBX /= 16;
			EDX &= 0x0f;
			[DS:ESI + 0xe0000000 + 4] = EAX;

			EAX = [SS:ESP + EDX * 4 + 4];
			EDX = EBX;
			(unsigned int) EBX /= 16;
			EDX &= 0x0f;
			[DS:ESI + 0xe0000000 + 0] = EAX;
			ESI += work->linebytes;

			EAX = [SS:ESP + EDX * 4 + 4];
			EDX = EBX;
			(unsigned int) EBX /= 16;
			EDX &= 0x0f;
			[DS:ESI + 0xe0000000 + 4] = EAX;

			EAX = [SS:ESP + EDX * 4 + 4];
			EDX = EBX;
			(unsigned int) EBX /= 16;
			EDX &= 0x0f;
			[DS:ESI + 0xe0000000 + 0] = EAX;
			ESI += work->linebytes;

			EAX = [SS:ESP + EDX * 4 + 4];
			EDX = EBX;
			(unsigned int) EBX /= 16;
			EDX &= 0x0f;
			[DS:ESI + 0xe0000000 + 4] = EAX;

			EAX = [SS:ESP + EDX * 4 + 4];
			[DS:ESI + 0xe0000000 + 0] = EAX;
			ESI += work->linebytes;
			ECX--;
		} while (!= 0);
		EAX = work->linebytes;
		POP(ECX);
		#if (!defined(QEMU))
			IMUL(EAX, -16);
		#else
			EAX *= 16;
			NEG(EAX);
		#endif
		LEA(ESI, [ESI + EAX + 8]);
		ECX--;
	} while (!= 0);
	ESP += 64;
	(offset) cmd = (offset) string;
//	AX = CS;
//	AX += 8;
//	ES = AX;

	asmout("JMP next_command");

opt1:
	/* half height */
	LEA((offset) string, [EBX + 36]);
//	LEA(EBX, [EBX + ECX * 4 + 36]);

	do {
		PUSH(ECX);
		(offset) font = *string;
		(offset) string += 4;
		ECX = 2;
		do {
			EBX = *font; /* 4lines */
			(offset) font += 4;
			EDX = EBX;
			(unsigned int) EBX /= 16;
			EDX &= 0x0f;
			EAX = [SS:ESP + EDX * 4 + 4];
			EDX = EBX;
			(unsigned int) EBX /= 16;
			EDX &= 0x0f;
			[DS:ESI + 0xe0000000 + 4] = EAX;

			EAX = [SS:ESP + EDX * 4 + 4];
			EDX = EBX;
			(unsigned int) EBX /= 16;
			EDX &= 0x0f;
			[DS:ESI + 0xe0000000 + 0] = EAX;
			ESI += work->linebytes;

			EAX = [SS:ESP + EDX * 4 + 4];
			EDX = EBX;
			(unsigned int) EBX /= 16;
			EDX &= 0x0f;
			[DS:ESI + 0xe0000000 + 4] = EAX;

			EAX = [SS:ESP + EDX * 4 + 4];
			EDX = EBX;
			(unsigned int) EBX /= 16;
			EDX &= 0x0f;
			[DS:ESI + 0xe0000000 + 0] = EAX;
			ESI += work->linebytes;

			EAX = [SS:ESP + EDX * 4 + 4];
			EDX = EBX;
			(unsigned int) EBX /= 16;
			EDX &= 0x0f;
			[DS:ESI + 0xe0000000 + 4] = EAX;

			EAX = [SS:ESP + EDX * 4 + 4];
			EDX = EBX;
			(unsigned int) EBX /= 16;
			EDX &= 0x0f;
			[DS:ESI + 0xe0000000 + 0] = EAX;
			ESI += work->linebytes;

			EAX = [SS:ESP + EDX * 4 + 4];
			EDX = EBX;
			(unsigned int) EBX /= 16;
			EDX &= 0x0f;
			[DS:ESI + 0xe0000000 + 4] = EAX;

			EAX = [SS:ESP + EDX * 4 + 4];
			[DS:ESI + 0xe0000000 + 0] = EAX;
			ESI += work->linebytes;
			ECX--;
		} while (!= 0);
		EAX = work->linebytes;
		POP(ECX);
		#if (!defined(QEMU))
			IMUL(EAX, -8);
		#else
			EAX *= 8;
			NEG(EAX);
		#endif
		LEA(ESI, [ESI + EAX + 8]);
		ECX--;
	} while (!= 0);
	ESP += 64;
	(offset) cmd = (offset) string;
	asmout("JMP next_command");

opt2:
	EAX = cmd[ 8]; /* x */
	ESI = cmd[12]; /* y */
	TEST(AL, 0x03);
	if (!= 0)
		goto error; /* 4の倍数以外はまだサポートしてない */

	IMUL(ESI, work->linebytes);
	ESI += EAX;

//	int *font == ES:EDI;
//	int *string == FS:EBP;
	ECX = cmd[32]; // length

	if (cmd[4] != 2)
		goto opt3;

	LEA((offset) string, [EBX + 36]);
//	LEA(EBX, [EBX + ECX * 4 + 36]);

	do {
		PUSH(ECX);
		(offset) font = *string;
		(offset) string += 4;
		ECX = 4;
		do {
			EAX = font[ 0]; /* 4dots */
			EDX = font[ 4];
			[DS:ESI + 0xe0000000 + 0] = EAX;
			[DS:ESI + 0xe0000000 + 4] = EDX;
			ESI += work->linebytes;
			EAX = font[ 8]; /* 4dots */
			EDX = font[12];
			[DS:ESI + 0xe0000000 + 0] = EAX;
			[DS:ESI + 0xe0000000 + 4] = EDX;
			ESI += work->linebytes;
			EAX = font[16]; /* 4dots */
			EDX = font[20];
			[DS:ESI + 0xe0000000 + 0] = EAX;
			[DS:ESI + 0xe0000000 + 4] = EDX;
			ESI += work->linebytes;
			EAX = font[24]; /* 4dots */
			EDX = font[28];
			(offset) font += 32;
			[DS:ESI + 0xe0000000 + 0] = EAX;
			[DS:ESI + 0xe0000000 + 4] = EDX;
			ESI += work->linebytes;
			ECX--;
		} while (!= 0);
		EAX = work->linebytes;
		POP(ECX);
		#if (!defined(QEMU))
			IMUL(EAX, -16);
		#else
			EAX *= 16;
			NEG(EAX);
		#endif
		LEA(ESI, [ESI + EAX + 8]);
		ECX--;
	} while (!= 0);
	(offset) cmd = (offset) string;
	asmout("JMP next_command");

opt3:
	/* half height */
	LEA((offset) string, [EBX + 36]);
//	LEA(EBX, [EBX + ECX * 4 + 36]);

	do {
		PUSH(ECX);
		(offset) font = *string;
		(offset) string += 4;
		ECX = 2;
		do {
			EAX = font[ 0]; /* 4dots */
			EDX = font[ 4];
			[DS:ESI + 0xe0000000 + 0] = EAX;
			[DS:ESI + 0xe0000000 + 4] = EDX;
			ESI += work->linebytes;
			EAX = font[ 8]; /* 4dots */
			EDX = font[12];
			[DS:ESI + 0xe0000000 + 0] = EAX;
			[DS:ESI + 0xe0000000 + 4] = EDX;
			ESI += work->linebytes;
			EAX = font[16]; /* 4dots */
			EDX = font[20];
			[DS:ESI + 0xe0000000 + 0] = EAX;
			[DS:ESI + 0xe0000000 + 4] = EDX;
			ESI += work->linebytes;
			EAX = font[24]; /* 4dots */
			EDX = font[28];
			(offset) font += 32;
			[DS:ESI + 0xe0000000 + 0] = EAX;
			[DS:ESI + 0xe0000000 + 4] = EDX;
			ESI += work->linebytes;
			ECX--;
		} while (!= 0);
		EAX = work->linebytes;
		POP(ECX);
		#if (!defined(QEMU))
			IMUL(EAX, -8);
		#else
			EAX *= 8;
			NEG(EAX);
		#endif
		LEA(ESI, [ESI + EAX + 8]);
		ECX--;
	} while (!= 0);
	(offset) cmd = (offset) string;
	asmout("JMP next_command");

opt_high:
/*
	0x0101, opt, x, y, col, bcol[20], dummy[24], dummy[28], len, str...
	optによって、x, yがofs:selになる
	opt8-10 : 0, 1, 2, 4(3) (0以外はRAM描画, dmy[24]がラインバイト)
	opt11 : extフラグ, strをfar-ptrにする(でも価値無しだな)
	opt12 : col無効化フラグに
	opt13 : bcol無効化フラグ
	opt14-15 : pset, and, or, xor
	とりあえず、opt:0x0100のみのサポートを追加しよう。
	optで関数のアドレスが決まり、それをループごとに呼ぶ。jmpでもよい。
*/
	if (EAX != 0x0100)
		goto error;
	PUSH(DS);
	EBP = cmd[24];
	LDS(ESI, cmd[8]);
	ECX = cmd[32]; /* len */
	DL = cmd[16]; /* col */
	DH = cmd[20]; /* bcol */
	(offset) cmd += 36;
	do {
		PUSH(ECX);
		PUSH(ESI);
		EDI = *cmd;
		(offset) cmd += 4;
		CL = 16;
		do {
			CH = [ES:EDI];
			EDI++;
			TEST(CH, 0x80);
			AL = DL;
			if (== 0)
				AL = DH;
			[DS:ESI] = AL;
			TEST(CH, 0x40);
			AL = DL;
			if (== 0)
				AL = DH;
			[DS:ESI + 1] = AL;
			TEST(CH, 0x20);
			AL = DL;
			if (== 0)
				AL = DH;
			[DS:ESI + 2] = AL;
			TEST(CH, 0x10);
			AL = DL;
			if (== 0)
				AL = DH;
			[DS:ESI + 3] = AL;
			TEST(CH, 0x08);
			AL = DL;
			if (== 0)
				AL = DH;
			[DS:ESI + 4] = AL;
			TEST(CH, 0x04);
			AL = DL;
			if (== 0)
				AL = DH;
			[DS:ESI + 5] = AL;
			TEST(CH, 0x02);
			AL = DL;
			if (== 0)
				AL = DH;
			[DS:ESI + 6] = AL;
			TEST(CH, 0x01);
			AL = DL;
			if (== 0)
				AL = DH;
			[DS:ESI + 7] = AL;
			ESI += EBP;
			CL--;
		} while (!= 0);
		POP(ESI);
		POP(ECX);
		ESI += 8;
		ECX--;
	} while (!= 0);
	POP(DS);
	asmout("JMP next_command");

error:
	INT(0x03);
}

void init_mousecursor()
{
	unsigned char *cursor0 == GS:ESI; /* [y][x] */
	int *cursor_buf == DS:EDI; /* [x][y] */
	GAPI_WORK *work == DS:0x0000;

	PUSH(DS);
	PUSH(ES);
	POP(DS); /* DS == work */

	LEA((offset) cursor_buf, work->mouse_pattern[0]);
	EDX = 0;

	ECX = 16;
	do {
		/* 1loop当たり、1line */
		DL = cursor0[ 0];
		DL |= cursor0[32];
		EDX >>= 4;
		asmout("MOV EAX,DWORD PTR CS:[#table+EDX*4]");
		DL = cursor0[32];
		EAX =~ EAX;
		EDX >>= 4;
		cursor_buf[  0] = EAX;
		asmout("MOV EAX,DWORD PTR CS:[#table+EDX*4]");
		DL = cursor0[ 0];
		EAX &= 0x0f0f0f0f;
		DL |= cursor0[32];
		cursor_buf[  4] = EAX;
		EDX &= 0x0f;
		asmout("MOV EAX,DWORD PTR CS:[#table+EDX*4]");
		DL = cursor0[32];
		EAX =~ EAX;
		EDX &= 0x0f;
		cursor_buf[128] = EAX;
		asmout("MOV EAX,DWORD PTR CS:[#table+EDX*4]");
		DL = cursor0[ 1];
		EAX &= 0x0f0f0f0f;
		DL |= cursor0[33];
		cursor_buf[132] = EAX;
		EDX >>= 4;
		asmout("MOV EAX,DWORD PTR CS:[#table+EDX*4]");
		DL = cursor0[33];
		EAX =~ EAX;
		EDX >>= 4;
		cursor_buf[256] = EAX;
		asmout("MOV EAX,DWORD PTR CS:[#table+EDX*4]");
		DL = cursor0[ 1];
		EAX &= 0x0f0f0f0f;
		DL |= cursor0[33];
		cursor_buf[260] = EAX;
		EDX &= 0x0f;
		asmout("MOV EAX,DWORD PTR CS:[#table+EDX*4]");
		DL = cursor0[33];
		EAX =~ EAX;
		EDX &= 0x0f;
		cursor_buf[384] = EAX;
		asmout("MOV EAX,DWORD PTR CS:[#table+EDX*4]");
		cursor_buf[512] = 0xffffffff;
		EAX &= 0x0f0f0f0f;
		(offset) cursor0 += 2;
		cursor_buf[388] = EAX;
		cursor_buf[516] = 0;
		(offset) cursor_buf += 8;
		ECX--;
	} while (!= 0);

	/* ずらしパターンの用意 */
	int *base == DS:ESI, *shift == DS:EDI;
	LEA((offset) base,  work->mouse_pattern[  0]);
	LEA((offset) shift, work->mouse_pattern[640]);
	EBP = 3;

	do {
		ECX = 32;
		do {
			EAX = base[  0];
			EDX = EAX;
			EAX *= 256;
			TEST(ECX, 1);
			EBX = base[128];
			if (== 0)
				EAX |= 0xff;
			shift[0] = EAX;
			EAX = EBX;
			SHLD(EBX, EDX, 8);
			EDX = base[256];
			shift[128] = EBX;
			EBX = EDX;
			SHLD(EDX, EAX, 8);
			EAX = base[384];
			shift[256] = EDX;
			EDX = EAX;
			SHLD(EAX, EBX, 8);
			EBX = base[512];
			shift[384] = EAX;
			SHLD(EBX, EDX, 8);
			(offset) base += 4;
			shift[512] = EBX;
			(offset) shift += 4;
			ECX--;
		} while (!= 0);
		(offset) base  += 512;
		(offset) shift += 512;
		EBP--;
	} while (!= 0);

	POP(DS);
	return;

	ALIGN(4);
table:
	DD(0x00000000); DD(0xff000000); DD(0x00ff0000); DD(0xffff0000);
	DD(0x0000ff00); DD(0xff00ff00); DD(0x00ffff00); DD(0xffffff00);
	DD(0x000000ff); DD(0xff0000ff); DD(0x00ff00ff); DD(0xffff00ff);
	DD(0x0000ffff); DD(0xff00ffff); DD(0x00ffffff); DD(0xffffffff);
}

void GAPI_init()
{
	int all_sel == 1 * 8;
	int *cmd == FS:EBX;

	cmd[4] = 0xffffffff; /* 終了 */
	(offset) cmd += 12;

	GAPI_WORK *workES == ES:0x0000;

	ECX = 0;
	workES->mx1 = 0x80000000; /* 非表示 */
	workES->lockcount = /* 0 */ ECX;
	workES->mouselock = /* 0 */ ECX;
	workES->VGA_mode = /* 0 */ ECX;
	workES->mouseflag = /* 0 */ CL;

	asmout("JMP next_command");
}

void GAPI_resetdevice()
{
	GAPI_WORK *work == ES:0x0000;
	int *cmd == FS:EBX;

	if (cmd[8] == 0x0020) {
		/* 解像度伝達 */
		EAX = cmd[12];
	//	ECX = cmd[16];
		work->linebytes = EAX;
		(offset) cmd += 20;
		asmout("JMP next_command");
	}

	// パレット初期化
	EDX = 0x03da;
	ECX = 0;
	CLI();
	IN(AL, DX);
	DL = 0xc0;
	do {
		EAX = ECX;
		OUT(DX, AL);
		ECX++;
		OUT(DX, AL);
	} while ((unsigned) ECX < 16);
	DL = 0xda;
	IN(AL, DX);
	DL = 0xc0;
	AL = 0x20;
	OUT(DX, AL);

	DL = 0xc8;
	EAX = 0;
	ECX = 16;
	OUT(DX, AL); // 最初のパレット番号
	unsigned char *pt == CS:ESI, rgb_dat == AL;
	/* (offset) pt = (offset) palette_table; */
	asmout("MOV ESI,OFFSET #palette_table");
	DL = 0xc9;
	do {
		rgb_dat = pt[0];
		rgb_dat /= 4; // 0〜255 → 0〜63
		OUT(DX, rgb_dat);
		rgb_dat = pt[1];
		rgb_dat /= 4; // 0〜255 → 0〜63
		OUT(DX, rgb_dat);
		rgb_dat = pt[2];
		rgb_dat /= 4; // 0〜255 → 0〜63
		OUT(DX, rgb_dat);
		(offset) pt += 3;
		ECX--;
	} while (!= 0);
	STI();
	cmd[4] = 0xffffffff; // 終了
	(offset) cmd += 12;

	CLI(); /* 64色用パレット設定 */
	DL = 0xc8;
	AL = 192;
	ECX = 0;
	OUT(DX, AL); // 最初のパレット番号
	DL = 0xc9;
	do {
		EAX = ECX;
		EAX &= 0x03;
		IMUL(EAX, 0x55); /* 00, 55, aa, ff */
		EAX >>= 2;
		OUT(DX, AL);
		EAX = ECX;
		EAX >>= 2;
		EAX &= 0x03;
		IMUL(EAX, 0x55);
		EAX >>= 2;
		OUT(DX, AL);
		EAX = ECX;
		ECX++;
		EAX >>= 4;
		EAX &= 0x03;
		IMUL(EAX, 0x55);
		EAX >>= 2;
		OUT(DX, AL);
	} while (CL < 64);
	STI();
	asmout("JMP next_command");

palette_table: // Red, Green, Blue
	// 0:黒, 7:暗い灰色, 8:明るい灰色, 6:バックの色, 15:白

	asmout("DB 000H, 000H, 000H,   084H, 000H, 000H,   000H, 084H, 000H,   084H, 084H, 000H");
	asmout("DB 000H, 000H, 084H,   084H, 000H, 084H,   000H, 084H, 084H,   084H, 084H, 084H");
	asmout("DB 0C6H, 0C6H, 0C6H,   0FFH, 000H, 000H,   000H, 0FFH, 000H,   0FFH, 0FFH, 000H");
	asmout("DB 000H, 000H, 0FFH,   0FFH, 000H, 0FFH,   000H, 0FFH, 0FFH,   0FFH, 0FFH, 0FFH");
}

void GAPI_mouse_drawsub16()
/* DS:ESIからy方向に64バイトを、ES:EDXへ転送。 */
/* 同時にES:ESIを描画 */
/* ただし、どちらもVRAM内のアドレス。 */
/* EAX, ECXのみ破壊。 */
{
	int *b == ES:EDX, *p == DS:ESI, *q == ES:EDI;
	PUSH((offset) p);
	EAX = p[0]; ECX = p[EBP]; b[ 0] = EAX; b[ 4] = ECX;
	EAX &= q[  0]; ECX &= q[  8]; EAX ^= q[  4]; ECX ^= q[ 12];
	p[0] = EAX; p[EBP] = ECX; LEA((offset) p, [ESI + EBP * 2]);
	EAX = p[0]; ECX = p[EBP]; b[ 8] = EAX; b[12] = ECX;
	EAX &= q[ 16]; ECX &= q[ 24]; EAX ^= q[ 20]; ECX ^= q[ 28];
	p[0] = EAX; p[EBP] = ECX; LEA((offset) p, [ESI + EBP * 2]);
	EAX = p[0]; ECX = p[EBP]; b[16] = EAX; b[20] = ECX;
	EAX &= q[ 32]; ECX &= q[ 40]; EAX ^= q[ 36]; ECX ^= q[ 44];
	p[0] = EAX; p[EBP] = ECX; LEA((offset) p, [ESI + EBP * 2]);
	EAX = p[0]; ECX = p[EBP]; b[24] = EAX; b[28] = ECX;
	EAX &= q[ 48]; ECX &= q[ 56]; EAX ^= q[ 52]; ECX ^= q[ 60];
	p[0] = EAX; p[EBP] = ECX; LEA((offset) p, [ESI + EBP * 2]);
	EAX = p[0]; ECX = p[EBP]; b[32] = EAX; b[36] = ECX;
	EAX &= q[ 64]; ECX &= q[ 72]; EAX ^= q[ 68]; ECX ^= q[ 76];
	p[0] = EAX; p[EBP] = ECX; LEA((offset) p, [ESI + EBP * 2]);
	EAX = p[0]; ECX = p[EBP]; b[40] = EAX; b[44] = ECX;
	EAX &= q[ 80]; ECX &= q[ 88]; EAX ^= q[ 84]; ECX ^= q[ 92];
	p[0] = EAX; p[EBP] = ECX; LEA((offset) p, [ESI + EBP * 2]);
	EAX = p[0]; ECX = p[EBP]; b[48] = EAX; b[52] = ECX;
	EAX &= q[ 96]; ECX &= q[104]; EAX ^= q[100]; ECX ^= q[108];
	p[0] = EAX; p[EBP] = ECX; LEA((offset) p, [ESI + EBP * 2]);
	EAX = p[0]; ECX = p[EBP]; b[56] = EAX; b[60] = ECX;
	EAX &= q[112]; ECX &= q[120]; EAX ^= q[116]; ECX ^= q[124];
	p[0] = EAX; p[EBP] = ECX;
	POP((offset) p);
	return;
}

void GAPI_mouse_erasesub16()
{
	int *b == ES:EDI, *p == DS:ESI;
	PUSH((offset) p);
	EAX = b[ 0]; ECX = b[ 4]; p[0] = EAX; p[EBP] = ECX; LEA((offset) p, [ESI + EBP * 2]);
	EAX = b[ 8]; ECX = b[12]; p[0] = EAX; p[EBP] = ECX; LEA((offset) p, [ESI + EBP * 2]);
	EAX = b[16]; ECX = b[20]; p[0] = EAX; p[EBP] = ECX; LEA((offset) p, [ESI + EBP * 2]);
	EAX = b[24]; ECX = b[28]; p[0] = EAX; p[EBP] = ECX; LEA((offset) p, [ESI + EBP * 2]);
	EAX = b[32]; ECX = b[36]; p[0] = EAX; p[EBP] = ECX; LEA((offset) p, [ESI + EBP * 2]);
	EAX = b[40]; ECX = b[44]; p[0] = EAX; p[EBP] = ECX; LEA((offset) p, [ESI + EBP * 2]);
	EAX = b[48]; ECX = b[52]; p[0] = EAX; p[EBP] = ECX; LEA((offset) p, [ESI + EBP * 2]);
	EAX = b[56]; ECX = b[60]; p[0] = EAX; p[EBP] = ECX;
	POP((offset) p);
	return;
}

void GAPI_putmouse()
/* 破壊レジスタ：EAX, ECX, EDX, ESI, EDI */
{
	GAPI_WORK *work == ES:0x0000;
	int *b /* backup */ == ES:EDX, *p /* cursor */ == DS:ESI, *q /* pattern */ == ES:EDI;
	unsigned char maskflag == BL;

	PUSH(EBP);
	PUSH(EBX);
	EBP = work->linebytes;
	maskflag = work->maskflag; /* 1のbitは書かない */
	work->mouseflag = 1;
	(offset) p = work->cursor_addr;
	LEA((offset) b, work->backup_buf[0]);
	(offset) q = work->pattern_addr; /* ANDパターンとXORパターンのセット */
	TEST(maskflag, 0x01);
	if (== 0)
		GAPI_mouse_drawsub16();
	(offset) p +=   4;
	(offset) b +=  64;
	(offset) q += 128;
	TEST(maskflag, 0x02);
	if (== 0)
		GAPI_mouse_drawsub16();
	(offset) p +=   4;
	(offset) b +=  64;
	(offset) q += 128;
	TEST(maskflag, 0x04);
	if (== 0)
		GAPI_mouse_drawsub16();
	(offset) p +=   4;
	(offset) b +=  64;
	(offset) q += 128;
	TEST(maskflag, 0x08);
	if (== 0)
		GAPI_mouse_drawsub16();
	(offset) p +=   4;
	(offset) b +=  64;
	(offset) q += 128;
	TEST(maskflag, 0x10);
	POP(EBX);
	if (== 0)
		GAPI_mouse_drawsub16();
	POP(EBP);
	return;
}

void GAPI_removemouse()
/* 破壊レジスタ：EAX, ECX, EDX, ESI, EDI */
{
	GAPI_WORK *work == ES:0x0000;
	int *b /* backup */ == ES:EDI, *p /* cursor */ == DS:ESI;
	unsigned char maskflag == DL;

	PUSH(EBP);
	EBP = work->linebytes;
	maskflag = work->maskflag; /* 1のbitは書かない */
	work->mouseflag = 0;
	(offset) p = work->cursor_addr;
	LEA((offset) b, work->backup_buf[0]);
	TEST(maskflag, 0x01);
	if (== 0)
		GAPI_mouse_erasesub16();
	(offset) p +=   4;
	(offset) b +=  64;
	TEST(maskflag, 0x02);
	if (== 0)
		GAPI_mouse_erasesub16();
	(offset) p +=   4;
	(offset) b +=  64;
	TEST(maskflag, 0x04);
	if (== 0)
		GAPI_mouse_erasesub16();
	(offset) p +=   4;
	(offset) b +=  64;
	TEST(maskflag, 0x08);
	if (== 0)
		GAPI_mouse_erasesub16();
	(offset) p +=   4;
	(offset) b +=  64;
	TEST(maskflag, 0x10);
	if (== 0)
		GAPI_mouse_erasesub16();
	POP(EBP);
	return;
}

void GAPI_clippingmouse()
/* VRAMに15ライン以上の余裕を仮定＆パターンの上部が欠けることもありえない */
/* (mx, my) : 共に符号付き整数 */
/* EBX以外を破壊 */
{
	GAPI_WORK *work == ES:0x0000;
	char *p == DS:EDI /* カーソルアドレス */, *q == ES:EAX;
	char maskflag == CL;
	signed int x == ESI, y == EBP, mouseline == EDX;

	maskflag = 0;
	x = work->mx;
	y = work->my;
	(offset) q = x;
	x &= /* ~0x03 */ 0xfffffffc;
	work->my0 = y;
	y += 16;
	work->mx0 = x;
	x += 20;
	work->my1 = y;
	y -= 16;
	TEST(/* (char) (offset) q */ AL, 0x03);
	/* (false) */ if (== 0) {
		x -= 4;
		maskflag = 0x10;
	}
	work->mx1 = x;
	x = (offset) q;
	(offset) q &= 0x03;
	(offset) q *= 128;
	EDX = work->linebytes;
	(offset) q *= 5;
	EDX -= 16;
	/* (false) */ if (x < 0) {
		work->mx0 = 0;
		maskflag |= 0x01;
		if (x < 0 - 4) {
			maskflag |= 0x03;
			if (x < 0 - 8) {
				maskflag |= 0x07;
				if (x < 0 - 12) {
					maskflag |= 0x0f;
				}
			}
		}
	} else /* (false) */ if (x >= EDX) {
		EDX += 16;
		work->mx1 = EDX;
		maskflag |= 0x10;
		EDX -= 12;
		if (x >= EDX) {
			EDX += 4;
			maskflag |= 0x18;
			if (x >= EDX) {
				EDX += 4;
				maskflag |= 0x1c;
				if (x >= EDX) {
					maskflag |= 0x1e;
				}
			}
		}
	}
	mouseline = 16;
	x &= /* ~0x03 */ 0xfffffffc;
	x += 0xe0000000;
//	/* (false) */ if (y < 0) {
//			work->my0 = 0;
//			mouseline += y;
//			(offset) q -= y;
//			y = 0;
//			(offset) p = 0;
//			goto skip_imul;
//	}
//	/* (false) */ if (y > 600 - 16) {
//			mouseline = 600;
//			work->my1 = mouseline;
//			mouseline -= y;
//	}
//	IMUL((offset) p, y, 100);
	(offset) p = y;
	IMUL((offset) p, work->linebytes);
skip_imul:
	work->maskflag = maskflag;
	work->mouseline = mouseline;
	(offset) q += (offset) work->mouse_pattern /* 384 */;
	(offset) p += x;
	work->pattern_addr = (offset) q;
	work->cursor_addr = (offset) p;
	return;
}

void GAPI_accesslock()
/* opt bit0  0:Lock 1:Unlock
       bit1  Lock時のオプション   0:nearポインタあり 1:なし
             Unlock時のオプション 0:範囲指定なし 1:あり
       bit8-31  Unlock-opt */
{
	int *cmd == FS:EBX;
	GAPI_WORK *work == ES:0x0000;

	EAX = cmd[8]; // opt
	if (AL == 0)
		goto lock_bitset;
	if (AL == 0x02)
		goto lock_bitnoset;
	if (AL == 0x01)
		goto unlock_optbit;
	if (AL == 0x03)
		goto unlock_area;
	INT(0x03);

lock_bitset:
	EAX = cmd[12]; // x0
	ECX = cmd[16]; // y0
	ESI = cmd[20]; // x1
	EDI = cmd[24]; // y1
	EBP = cmd[28]; // ofs
	cmd[4] = 0xffffffff; /* 終了 */
	(offset) cmd += 32;
	CLI();
	work->lockcount++;
	if ((signed) EAX /* x0 */ < work->mx1) {
		if ((signed) ECX /* y0 */ < work->my1) {
			if ((signed) ESI /* x1 */ > work->mx0) {
				if ((signed) EDI /* y1 */ > work->my0) {
					if (work->mouseflag != 0) {
						GAPI_removemouse(); // remove mouse (mouseflag = 0)
					}
					work->mouselock++;
					(char) [FS:EBP + 1] |= 0x01; // mouse
				}
			}
		}
	}
	STI();
	asmout("JMP next_command");

lock_bitnoset:
	EAX = cmd[12]; // x0
	ECX = cmd[16]; // y0
	ESI = cmd[20]; // x1
	EDI = cmd[24]; // y1
	cmd[4] = 0xffffffff; /* 終了 */
	(offset) cmd += 28;
	CLI();
	work->lockcount++;
	if ((signed) EAX /* x0 */ < work->mx1) {
		if ((signed) ECX /* y0 */ < work->my1) {
			if ((signed) ESI /* x1 */ > work->mx0) {
				if ((signed) EDI /* y1 */ > work->my0) {
					if (work->mouseflag != 0) {
						GAPI_removemouse(); // remove mouse (mouseflag = 0)
					}
					work->mouselock++;
				}
			}
		}
	}
	STI();
	asmout("JMP next_command");

unlock_optbit:
	CLI();
	work->lockcount--;
	if (!= 0) {
		TEST(AH, 0x01);
		if (!= 0) {
			work->mouselock--;
			if (== 0) {
				/* マウスを移動させる時に、mouselockが0x80000000にされるので、
				   マウスが非表示中に移動すると、これは成立しなくなる。 */
				GAPI_putmouse(); /* put mouse (mouseflag = 1) */
				/* mx1をチェックしなくていいのか？ */
			}
		}
		STI();
		cmd[4] = 0xffffffff; /* 終了 */
		(offset) cmd += 12;
		asmout("JMP next_command");
	}
	work->mouselock = 0;
	if (work->mx1 != 0x80000000 /* mx1がこの値の時は、非表示を意味する */) {
		if (work->mouseflag == 0 /* mouse erased */) {
			GAPI_clippingmouse(); /* mx0, my0, mx1, my1を設定 */
			GAPI_putmouse(); /* put mouse (mouseflag = 1) */
		}
	}
	STI();
	cmd[4] = 0xffffffff; /* 終了 */
	(offset) cmd += 12;
	asmout("JMP next_command");

unlock_area:
	EAX = cmd[12]; // x0
	ECX = cmd[16]; // y0
	ESI = cmd[20]; // x1
	EDI = cmd[24]; // y1
	CLI();
	work->lockcount--;
	if (!= 0) {
		if ((signed) EAX /* x0 */ < work->mx1) {
			if ((signed) ECX /* y0 */ < work->my1) {
				if ((signed) ESI /* x1 */ > work->mx0) {
					if ((signed) EDI /* y1 */ > work->my0) {
						work->mouselock--;
						if (== 0) {
							/* マウスを移動させる時に、mouselockが0にされるので、
							   マウスが一時消去中に移動すると、これは成立しなくなる。
							   マウスが非表示中は最初のmx1の比較が成立しない */
							GAPI_putmouse(); /* put mouse (mouseflag = 1) */
						}
					}
				}
			}
		}
		STI();
		cmd[4] = 0xffffffff; /* 終了 */
		(offset) cmd += 28;
		asmout("JMP next_command");
	}
	work->mouselock = 0;
	if (work->mx1 != 0x80000000 /* mx1がこの値の時は、非表示を意味する */) {
		if (work->mouseflag == 0 /* mouse erased */) {
			GAPI_clippingmouse(); /* mx0, my0, mx1, my1を設定 */
			GAPI_putmouse(); /* put mouse (mouseflag = 1) */
		}
	}
	STI();
	cmd[4] = 0xffffffff; /* 終了 */
	(offset) cmd += 28;
	asmout("JMP next_command");
}

void GAPI_mouse()
/* option:bit0  直接指定(0)/間接指定(1)
   option:bit5,4  16x16(00)/32x31(01)
   option:bit7,6  マスクパターンありのモノクロ(00),マスクパターンありのカラー(10)
   option:bit9,8  カーソルパターンストア(00),カーソル表示(01),カーソル消去(10),カーソル移動(11)
     01,11では、カーソル座標を指定する。このコマンドでは、マウスカーソルは一つしか制御できない。
     デフォルトでは、マウスカーソルと他のグラフィックコマンドとの関係を解消したりもしない。 */
{
	int *cmd == FS:EBX;
	GAPI_WORK *work == ES:0x0000;

	cmd[4] = 0xffffffff; /* コマンド終了 */
	EAX = cmd[8];
	CLI();
	TEST(AH, 0x03);
	if (== 0) {
		PUSH(GS);
		PUSH(EBX);
		LGS(ESI, [FS:EBX + 12]);
		init_mousecursor();
		POP(EBX);
		POP(GS);
		STI();
		(offset) cmd += 20;
		asmout("JMP next_command");
	}
	TEST(AH, 0x02);
	if (!= 0) {
		/* カーソルを消す */
		if (work->mouseflag != 0) {
			GAPI_removemouse(); /* remove mouse (mouseflag = 0) */
			EAX = cmd[8];
		}
		TEST(AH, 0x01);
		if (== 0)
			work->mx1 = 0x80000000; /* 非表示モード */
	}
	TEST(AH, 0x01);
	if (!= 0) {
		/* カーソルを描く */
		ECX = cmd[12];
		EDX = cmd[16];
		work->mx = ECX;
		work->my = EDX;
		if (work->lockcount == 0) {
			GAPI_clippingmouse(); /* mx0, my0, mx1, my1を設定 */
			GAPI_putmouse(); /* put mouse (mouseflag = 1) */
		} else {
			work->mouselock = 0x80000000;
		}
		STI();
		(offset) cmd += 20;
		asmout("JMP next_command");
	}
	STI();
	(offset) cmd += 12;
	asmout("JMP next_command");
}

void GAPI_error()
{
	INT(0x03);
}

void GAPI_putbox()
{
	/* 256色ブロック転送 */
	/* cmd, opt, x0, y0, xsize, ysize, yskip, ofs, sel */

	/* アラインにはまだほとんど配慮していない */

	GAPI_WORK *work == ES:0x0000;
	int *cmd == FS:EBX;
	unsigned char *p == DS:ESI, *q == ES:EDI;
	unsigned int *pi == DS:ESI, *qi == ES:EDI;
	unsigned short *ps == DS:ESI;

	PUSH(ES);
	PUSH(DS);
	PUSH(EBP);
	EBP = work->linebytes;
	PUSH(DS);
	POP(ES);
	(offset) q = cmd[12]; /* y */
	LDS(ESI, cmd[28]);
	IMUL(EDI, EBP);
	(offset) q += cmd[ 8]; /* x */
	EBP -= cmd[16]; /* xsize */
	EDX = cmd[20]; /* ysize */
	(offset) q += 0xe0000000;
	AL = (char) cmd[4];
	CLD();
	TEST(AL, 0x10);
	if (!= 0)
		goto putbox1;
	AL &= 0x2f;
	if (AL == 0x01) {
		do {
			ECX = cmd[16]; /* xsize */
			do {
				TEST((offset) q, 3);
				if (== 0)
					break;
				AL = *p;
				(offset) p++;
				*q = AL;
				(offset) q++;
				ECX--;
			} while (!= 0);
			if (ECX >= 4) {
				EAX = ECX;
				ECX /= 4;
				REP(); MOVSD();
				ECX = EAX;
			}
			ECX &= 3;
			if (!= 0) {
				do {
					AL = *p;
					(offset) p++;
					*q = AL;
					(offset) q++;
					ECX--;
				} while (!= 0);
			}
			(offset) p += cmd[24]; /* yskip */
			(offset) q += EBP;
			EDX--;
		} while (!= 0);
		(offset) cmd += 36;
		POP(EBP);
		POP(DS);
		POP(ES);
		asmout("JMP next_command");
	}
	if (AL == 0x22) {
		/* ダイレクトカラー16bit, RRRRRGGG_GGGBBBBB */
		/* タイリング無し */
		do {
			ECX = cmd[16]; /* xsize */
			PUSH(EDX);
#if 0
			PUSH(EBP);
			do {
				EAX = *ps;
				(offset) ps += 2;
				EAX &= 0xc618; /* RR000GG0_000BB000 */
				EDX = EAX;
				LEA(EBP, [EAX + 0x60]); /* RR000GG0_011BB000 */
				EAX >>= 14; /*                RR */
				EDX >>=  7; /*         RR000GG00 */
				EBP *= 2;   /* RR000GG0011BB0000 */
				EAX |= EDX;
				EAX |= EBP;
				*q = AL;
				(offset) q++;
				ECX--;
			} while (!= 0);
			POP(EBP);
#endif

#if 1
			do {
				EAX = *ps;
				(offset) ps += 2;
				EAX &= 0xc618; /* RR000GG0_000BB000 */
				EDX = EAX;
				EAX >>= 14; /*                                      RR */
				LEA(EAX, [EAX + EDX * 2 + 0xc0]); /* RR000GG0011BB0000 (EDX * 2 + 0xc0) */
				EDX >>=  7; /*                               RR000GG00 */
				AL |= DL;
				*q = AL;
				(offset) q++;
				ECX--;
			} while (!= 0);
#endif
			POP(EDX);
			(offset) p += cmd[24]; /* yskip */
			(offset) q += EBP;
			EDX--;
		} while (!= 0);
		(offset) cmd += 36;
		POP(EBP);
		POP(DS);
		POP(ES);
		asmout("JMP next_command");
	}
	if (AL == 0x24) {
		/* ダイレクトカラー32bit(24bit) */
		/* タイリング無し */
		do {
			ECX = cmd[16]; /* xsize */
			PUSH(EDX);
#if 0
			PUSH(EBP);
			do {
				EAX = *pi;
				(offset) pi += 4;
				EAX &= 0xc0c0c0; /* RR000000_GG000000_BB000000 */
				EDX = EAX;
				LEA(EBP, [EAX + 0x0300]); /* 11BB000000 */
				EAX >>= 22; /*       RR */
				EDX >>= 12; /*     GG00 */
				EBP >>=  2; /* 11BB0000 */
				EAX |= EDX;
				EAX |= EBP;
				*q = AL;
				(offset) q++;
				ECX--;
			} while (!= 0);
			POP(EBP);
#endif
#if 1
			do {
				EAX = *pi;
				(offset) pi += 4;
				EAX &= 0xc0c0c0; /* RR000000_GG000000_BB000000 */
				EDX = EAX;
				EAX >>= 20; /*                           RR00 */
				LEA(EAX, [EAX + EDX + 0x0300]); /* 11BB000000 */
				EDX >>= 12; /*     GG00 */
				EAX >>=  2; /* 11BB00RR */
				AL |= DL;
				*q = AL;
				(offset) q++;
				ECX--;
			} while (!= 0);
#endif
			POP(EDX);
			(offset) p += cmd[24]; /* yskip */
			(offset) q += EBP;
			EDX--;
		} while (!= 0);
		(offset) cmd += 36;
		POP(EBP);
		POP(DS);
		POP(ES);
		asmout("JMP next_command");
	}
	if (AL == 0x02) {
		/* ダイレクトカラー16bit, RRRRRGGG_GGGBBBBB */
		/* タイリングあり */
		PUSH((offset) cmd);
		PUSH(EBP); /* qに対するskip */
		PUSH(cmd[24]); /* pに対するskip */
		PUSH(EDX); /* ysize */
		PUSH(cmd[16]); /* xsize */
		BH = cmd[12]; /* y */
		do {
			BH &= 0x01;
			SETNZ(AL);
			TEST((offset) q, 0x01);
			SETNZ(DL);
			AL ^= DL;
			AL *= 2;
			EBP = [SS:ESP + 0]; /* xsize */
			BH |= AL;
			do {
				PUSH(EDI);
				EDX = *ps; /* green */
				(offset) p += 2;
				EAX = EDX; /* blue & red */
				EDX >>= 3;
				EAX &= 0xf81f; /* RRRRRGGG_GGGBBBBB */
				EDX &= 0xf8;
				BL = 0xc0;
				LEA(EDI, [EAX + EAX * 2]);
				LEA(ECX, [EDX + EDX * 2]);
				EDX *= 16;
				EAX *= 16;
				EDX -= ECX; /* これで13倍 */
				EAX -= EDI;
				POP(EDI);
				DH += 3;
				EAX += 0x030060;
				DL = DH; /* green */
				ECX = EAX;
				EAX >>= 8; /* AH */
				ECX <<= 3; /* CH */
				AL = AH; /* red */
				CL = CH; /* blue */
				DH &= 0x03;
				AH &= 0x03;
				CH &= 0x03;
				DL /= 4;
				AL /= 4;
				CL /= 4;
				CMP(DH, BH);
				SBB(DL, 0);
				CMP(AH, BH);
				SBB(AL, 0);
				CMP(CH, BH);
				SBB(CL, 0);
				DL *= 4;
				CL *= 16;
				AL |= BL;
				DL |= CL;
				AL |= DL;
				BH ^= 0x02;
				*q = AL;
				(offset) q++;
				EBP--;
			} while (!= 0);
			BH ^= 0x01;
			(offset) p += [SS:ESP +  8];
			(offset) q += [SS:ESP + 12];
			(int) [SS:ESP + 4]--; /* xsize */
		} while (!= 0);
		ESP += 16;
		POP((offset) cmd);
		(offset) cmd += 36;
		POP(EBP);
		POP(DS);
		POP(ES);
		asmout("JMP next_command");
	}
	if (AL == 0x04) {
		/* ダイレクトカラー32bit(24bit) */
		/* タイリングあり */
		PUSH((offset) cmd);
		PUSH(EBP); /* qに対するskip */
		PUSH(cmd[24]); /* pに対するskip */
		PUSH(EDX); /* ysize */
		PUSH(cmd[16]); /* xsize */
		BH = cmd[12]; /* y */
		do {
			BH &= 0x01;
			SETNZ(AL);
			TEST((offset) q, 0x01);
			SETNZ(DL);
			AL ^= DL;
			AL *= 2;
			EBP = [SS:ESP + 0]; /* xsize */
			BH |= AL;
			do {
				PUSH(EDI);
				EDX = *pi; /* green */
				(offset) p += 4;
				EAX = EDX; /* blue & red */
				EDX >>= 8;
				EAX &= 0xff00ff;
				EDX &= 0x0000ff;
				BL = 0xc0;
				LEA(EDI, [EAX + EAX * 2]);
				LEA(ECX, [EDX + EDX * 2]);
				EDX *= 16;
				EAX *= 16;
				EDX -= ECX; /* これで13倍 */
				EAX -= EDI;
				POP(EDI);
				DH += 3;
				EAX += 0x03000300;
				DL = DH; /* green */
				ECX = EAX;
				EAX >>= 16; /* AH */
				DH &= 0x03;
				CL = CH; /* blue */
				AL = AH; /* red */
				CH &= 0x03;
				AH &= 0x03;
				DL /= 4;
				AL /= 4;
				CL /= 4;
				CMP(DH, BH);
				SBB(DL, 0);
				CMP(AH, BH);
				SBB(AL, 0);
				CMP(CH, BH);
				SBB(CL, 0);
				DL *= 4;
				CL *= 16;
				AL |= BL;
				DL |= CL;
				AL |= DL;
				BH ^= 0x02;
				*q = AL;
				(offset) q++;
				EBP--;
			} while (!= 0);
			BH ^= 0x01;
			(offset) p += [SS:ESP +  8];
			(offset) q += [SS:ESP + 12];
			(int) [SS:ESP + 4]--; /* xsize */
		} while (!= 0);
		ESP += 16;
		POP((offset) cmd);
		(offset) cmd += 36;
		POP(EBP);
		POP(DS);
		POP(ES);
		asmout("JMP next_command");
	}
	INT(0x03);
putbox1:
	AH = (char) cmd[36];
	do {
		ECX = cmd[16]; /* xsize */
		do {
			AL = *p;
			(offset) p++;
			if (AH != AL)
				*q = AL;
			(offset) q++;
			ECX--;
		} while (!= 0);
		(offset) p += cmd[24]; /* yskip */
		(offset) q += EBP;
		EDX--;
	} while (!= 0);
	(offset) cmd += 40;
	POP(EBP);
	POP(DS);
	POP(ES);
	asmout("JMP next_command");
}

void near GAPI_linesub_pset()
/*
	ESI : 初期x
	EDI : 初期y
	EDX : 増分値x
	EBX : 増分値y
	EBP : ループ回数
	EAX : カラー
*/
{
	GAPI_WORK *work == ES:0x0000;
	PUSH(EBP);
	PUSH(EAX);
	ECX = EDI;
	EAX = ESI;
	(unsigned int) ECX >>= 16;
	(unsigned int) EAX >>= 16;
	IMUL(ECX, work->linebytes);
	LEA(EBP, [EAX + ECX + 0xe0000000]);
	EAX = 0x00010000;
	ECX = 0xffff0000;
	if (EBX == EAX) {
		if (EDX == EAX)
			goto line_xp1_yp1;
		if ((signed) > )
			goto general;
		if (EDX >= 0)
			goto line_xpd_yp1;
		if (EDX == ECX)
			goto line_xm1_yp1;
		if ((signed) < )
			goto line_xmd_yp1;
	} else if (EBX == ECX) {
		if (EDX == EAX)
			goto line_xp1_ym1;
		if ((signed) > )
			goto general;
		if (EDX >= 0)
			goto line_xpd_ym1;
		if (EDX == ECX)
			goto line_xm1_ym1;
		if ((signed) < )
			goto line_xmd_ym1;
	} else if (EDX == EAX) {
	//	if (EBX == EAX)
	//		goto line_xp1_yp1;
		if ((signed) EBX > EAX)
			goto general;
		if (EBX >= 0)
			goto line_xp1_ypd;
	//	if (EBX == ECX)
	//		goto line_xp1_ym1;
		if ((signed) EBX < ECX)
			goto line_xp1_ymd;
	} else if (EDX == ECX) {
	//	if (EBX == EAX)
	//		goto line_xm1_yp1;
		if ((signed) EBX > EAX)
			goto general;
		if (EBX >= 0)
			goto line_xm1_ypd;
	//	if (EBX == ECX)
	//		goto line_xm1_ym1;
		if ((signed) EBX < ECX)
			goto line_xm1_ymd;
	}

general:
	POP(EAX);
	POP(EBP);
	PUSH(EDX);
	do {
		EDX = EDI;
		ECX = ESI;
		(unsigned int) EDX >>= 16;
		(unsigned int) ECX >>= 16;
		IMUL(EDX, work->linebytes);
		ESI += [SS:ESP];
		EDI += EBX;
		(char) [DS:EDX + ECX + 0xe0000000] = AL;
		EBP--;
	} while (!= 0);
	POP(EDX);
	return;

line_xpd_yp1:
	EDI = EBP;
	POP(EAX);
	EBP = work->linebytes;
line_xpmd_yp1:
	ESI <<= 16;
	POP(ECX);
	EDX <<= 16;
	do {
		(char) [DS:EDI] = AL;
		ESI += EDX;
		ADC(EDI, EBP);
		ECX--;
	} while (!= 0);
	return;

line_xmd_yp1:
	EDI = EBP;
	POP(EAX);
	EBP = work->linebytes;
	EBP--;
	goto line_xpmd_yp1;

#if 0
	ESI <<= 16;
	POP(ECX);
	EDX <<= 16;
	do {
		(char) [DS:EDI] = AL;
		ESI += EDX;
		ADC(EDI, TWVSW - 1); /* CF == 1なら+TWVSW, CF == 0なら+TWVSW - 1 */
		ECX--;
	} while (!= 0);
	return;
#endif

line_xpd_ym1:
	EDI = EBP;
	POP(EAX);
	EBP = 0;
	EBP -= work->linebytes;
	goto line_xpmd_yp1;

#if 0
	ESI <<= 16;
	POP(ECX);
	EDX <<= 16;
	do {
		(char) [DS:EDI] = AL;
		ESI += EDX;
		ADC(EDI, 0 - TWVSW);
		ECX--;
	} while (!= 0);
	return;
#endif

line_xmd_ym1:
	EDI = EBP;
	POP(EAX);
	EBP = -1;
	EBP -= work->linebytes;
	goto line_xpmd_yp1;

#if 0
	ESI <<= 16;
	POP(ECX);
	EDX <<= 16;
	do {
		(char) [DS:EDI] = AL;
		ESI += EDX;
		ADC(EDI, 0 - TWVSW - 1); /* CF == 1なら-TWVSW, CF == 0なら-TWVSW - 1 */
		ECX--;
	} while (!= 0);
	return;
#endif

line_xp1_ypd:
	ESI = EBP;
	POP(EAX);
	EDI <<= 16;
	POP(ECX);
	EBX <<= 16;
	do {
		EDI += EBX;
		SBB(EDX, EDX); /* CF == 0ならEDX = 0, CF == 1ならEDX = -1 */
		(char) [DS:ESI] = AL;
		EDX &= work->linebytes;
	//	ESI++;
	//	ESI += EDX;
		ECX--;
		LEA(ESI, [ESI + EDX + 1]);
	} while (!= 0);
	return;

line_xp1_ymd:
	ESI = EBP;
	POP(EAX);
	EDI <<= 16;
	POP(ECX);
	EBX <<= 16;
	do {
		EDX = 0;
		EDI += EBX;
		ADC(EDX, 0xffffffff); /* CF == 0ならEDX = -1, CF == 1ならEDX = 0 */
		(char) [DS:ESI] = AL;
		EDX &= work->linebytes;
		NEG(EDX);
	//	ESI++;
	//	ESI += EDX;
		ECX--;
		LEA(ESI, [ESI + EDX + 1]);
	} while (!= 0);
	return;

line_xm1_ypd:
	ESI = EBP;
	POP(EAX);
	EDI <<= 16;
	POP(ECX);
	EBX <<= 16;
	do {
		EDI += EBX;
		SBB(EDX, EDX); /* CF == 0ならEDX = 0, CF == 1ならEDX = -1 */
		(char) [DS:ESI] = AL;
		EDX &= work->linebytes;
	//	ESI--;
	//	ESI += EDX;
		ECX--;
		LEA(ESI, [ESI + EDX - 1]);
	} while (!= 0);
	return;

line_xm1_ymd:
	ESI = EBP;
	POP(EAX);
	EDI <<= 16;
	POP(ECX);
	EBX <<= 16;
	do {
		EDX = 0;
		EDI += EBX;
		ADC(EDX, 0xffffffff); /* CF == 0ならEDX = -1, CF == 1ならEDX = 0 */
		(char) [DS:ESI] = AL;
		EDX &= work->linebytes;
		NEG(EDX);
	//	ESI--;
	//	ESI += EDX;
		ECX--;
		LEA(ESI, [ESI + EDX - 1]);
	} while (!= 0);
	return;

line_xp1_yp1:
	EDX = work->linebytes;
	EDX++;
line_x1_y1:
	POP(EAX);
	ESI = EBP;
	POP(ECX);
	do {
		(char) [DS:ESI] = AL;
		ESI += EDX;
		ECX--;
	} while (!= 0);
	return;

line_xp1_ym1:
	EDX = 1;
	EDX -= work->linebytes;
	goto line_x1_y1;

line_xm1_yp1:
	EDX = work->linebytes;
	EDX--;
	goto line_x1_y1;

line_xm1_ym1:
	EDX = -1;
	EDX -= work->linebytes;
	goto line_x1_y1;
}

void GAPI_linesub_xor()
/*
	ESI : 初期x
	EDI : 初期y
	EDX : 増分値x
	EBX : 増分値y
	EBP : ループ回数
	EAX : カラー
*/
{
	GAPI_WORK *work == ES:0x0000;
	PUSH(EDX);
	do {
		EDX = EDI;
		ECX = ESI;
		(unsigned int) EDX >>= 16;
		(unsigned int) ECX >>= 16;
		IMUL(EDX, work->linebytes);
		ESI += [SS:ESP];
		EDI += EBX;
		(char) [DS:EDX + ECX + 0xe0000000] ^= AL;
		EBP--;
	} while (!= 0);
	POP(EDX);
	return;
}

void near GAPI_linesub_or()
/*
	ESI : 初期x
	EDI : 初期y
	EDX : 増分値x
	EBX : 増分値y
	EBP : ループ回数
	EAX : カラー
*/
{
	GAPI_WORK *work == ES:0x0000;
	PUSH(EDX);
	do {
		EDX = EDI;
		ECX = ESI;
		(unsigned int) EDX >>= 16;
		(unsigned int) ECX >>= 16;
		IMUL(EDX, work->linebytes);
		ESI += [SS:ESP];
		EDI += EBX;
		(char) [DS:EDX + ECX + 0xe0000000] |= AL;
		EBP--;
	} while (!= 0);
	POP(EDX);
	return;
}

void near GAPI_linesub_and()
/*
	ESI : 初期x
	EDI : 初期y
	EDX : 増分値x
	EBX : 増分値y
	EBP : ループ回数
	EAX : カラー
*/
{
	GAPI_WORK *work == ES:0x0000;
	PUSH(EDX);
	do {
		EDX = EDI;
		ECX = ESI;
		(unsigned int) EDX >>= 16;
		(unsigned int) ECX >>= 16;
		IMUL(EDX, work->linebytes);
		ESI += [SS:ESP];
		EDI += EBX;
		(char) [DS:EDX + ECX + 0xe0000000] &= AL;
		EBP--;
	} while (!= 0);
	POP(EDX);
	return;
}

void near GAPI_lineardots()
{
	/* 斜め線を引くためなどに使う(等間隔で点を打つこともできる) */
	/* cmd, opt, x0, y0, sx, sy, lines, ofs, sel */
	/* sxとsyは利用していない */

	/* データーの形式 */
	/* x0, y0, dx, dy, dots, color */
	/* x0, y0, dx, dyは固定少数点 */

	int *cmd == FS:EBX;
	int *dat == GS:EAX;

	PUSH(GS);
	PUSH(EBP);
	ECX = cmd[ 4];
	EBP = cmd[24];
	ECX >>= 6;
	asmout("LGS EAX,DWORD FS:[EBX+28]");
	PUSH((offset) cmd);
	ESI = cmd[ 8];
	EDI = cmd[12];
	if (== 0) {
		do {
			PUSH(ESI);
			EDX = dat[ 8]; /* dx */
			PUSH(EDI);
			EBX = dat[12]; /* dy */
			PUSH(EBP);
			ESI <<= 16;
			EDI <<= 16;
			PUSH((offset) dat);
			ESI += dat[ 0]; /* x0 */
			EDI += dat[ 4]; /* y0 */
			EBP = dat[16]; /* dots */
			EAX = dat[20]; /* color */
			GAPI_linesub_pset();
			POP((offset) dat);
			POP(EBP);
			(offset) dat += 24;
			POP(EDI);
			EBP--;
			POP(ESI);
		} while (!= 0);
		POP((offset) cmd);
		POP(EBP);
		(offset) cmd += 36;
		POP(GS);
		asmout("JMP next_command");
	}
	ECX--;
	if (== 0) {
		do {
			PUSH(ESI);
			EDX = dat[ 8]; /* dx */
			PUSH(EDI);
			EBX = dat[12]; /* dy */
			PUSH(EBP);
			ESI <<= 16;
			EDI <<= 16;
			PUSH((offset) dat);
			ESI += dat[ 0]; /* x0 */
			EDI += dat[ 4]; /* y0 */
			EBP = dat[16]; /* dots */
			EAX = dat[20]; /* color */
			GAPI_linesub_and();
			POP((offset) dat);
			POP(EBP);
			(offset) dat += 24;
			POP(EDI);
			EBP--;
			POP(ESI);
		} while (!= 0);
		POP((offset) cmd);
		POP(EBP);
		(offset) cmd += 36;
		POP(GS);
		asmout("JMP next_command");
	}
	ECX--;
	if (== 0) {
		do {
			PUSH(ESI);
			EDX = dat[ 8]; /* dx */
			PUSH(EDI);
			EBX = dat[12]; /* dy */
			PUSH(EBP);
			ESI <<= 16;
			EDI <<= 16;
			PUSH((offset) dat);
			ESI += dat[ 0]; /* x0 */
			EDI += dat[ 4]; /* y0 */
			EBP = dat[16]; /* dots */
			EAX = dat[20]; /* color */
			GAPI_linesub_or();
			POP((offset) dat);
			POP(EBP);
			(offset) dat += 24;
			POP(EDI);
			EBP--;
			POP(ESI);
		} while (!= 0);
		POP((offset) cmd);
		POP(EBP);
		(offset) cmd += 36;
		POP(GS);
		asmout("JMP next_command");
	}
//	ECX--;
//	if (== 0) {
		do {
			PUSH(ESI);
			EDX = dat[ 8]; /* dx */
			PUSH(EDI);
			EBX = dat[12]; /* dy */
			PUSH(EBP);
			ESI <<= 16;
			EDI <<= 16;
			PUSH((offset) dat);
			ESI += dat[ 0]; /* x0 */
			EDI += dat[ 4]; /* y0 */
			EBP = dat[16]; /* dots */
			EAX = dat[20]; /* color */
			GAPI_linesub_xor();
			POP((offset) dat);
			POP(EBP);
			(offset) dat += 24;
			POP(EDI);
			EBP--;
			POP(ESI);
		} while (!= 0);
		POP((offset) cmd);
		POP(EBP);
		(offset) cmd += 36;
		POP(GS);
		asmout("JMP next_command");
//	}
}

void GAPI_points()
{
	/* 点を打つ */
	/* cmd, opt, x0, y0, sx, sy, lines, ofs, sel */
	/* sxとsyは利用していない */

	/* データーの形式 */
	/* x0, y0, color */

	GAPI_WORK *work == ES:0x0000;
	int *cmd == FS:EBX;
	int *dat == GS:EDX;

	PUSH(GS);
	EAX = cmd[ 4];
	ECX = cmd[24];
	asmout("LGS EDX,DWORD FS:[EBX+28]");
	ESI = cmd[ 8];
	EDI = cmd[12];
	(offset) cmd += 36;
	PUSH(ESI);
	EAX >>= 6;
	PUSH(EDI);
	if (== 0) {
		do {
			ESI += dat[0]; /* x0 */
			EDI += dat[4]; /* y0 */
			EAX = dat[8]; /* color */
			IMUL(EDI, work->linebytes);
			(offset) dat += 12;
			(char) [DS:EDI + ESI + 0xe0000000] = AL;
			ECX--;
			ESI = [SS:ESP + 4];
			EDI = [SS:ESP + 0];
		} while (!= 0);
		POP(EAX);
		POP(ECX);
		POP(GS);
		asmout("JMP next_command");
	}
	EAX--;
	if (== 0) {
		do {
			ESI += dat[0]; /* x0 */
			EDI += dat[4]; /* y0 */
			EAX = dat[8]; /* color */
			IMUL(EDI, work->linebytes);
			(offset) dat += 12;
			(char) [DS:EDI + ESI + 0xe0000000] &= AL;
			ECX--;
			ESI = [SS:ESP + 4];
			EDI = [SS:ESP + 0];
		} while (!= 0);
		POP(EAX);
		POP(ECX);
		POP(GS);
		asmout("JMP next_command");
	}
	EAX--;
	if (== 0) {
		do {
			ESI += dat[0]; /* x0 */
			EDI += dat[4]; /* y0 */
			EAX = dat[8]; /* color */
			IMUL(EDI, work->linebytes);
			(offset) dat += 12;
			(char) [DS:EDI + ESI + 0xe0000000] |= AL;
			ECX--;
			ESI = [SS:ESP + 4];
			EDI = [SS:ESP + 0];
		} while (!= 0);
		POP(EAX);
		POP(ECX);
		POP(GS);
		asmout("JMP next_command");
	}
//	EAX--;
//	if (== 0) {
		do {
			ESI += dat[0]; /* x0 */
			EDI += dat[4]; /* y0 */
			EAX = dat[8]; /* color */
			IMUL(EDI, work->linebytes);
			(offset) dat += 12;
			(char) [DS:EDI + ESI + 0xe0000000] ^= AL;
			ECX--;
			ESI = [SS:ESP + 4];
			EDI = [SS:ESP + 0];
		} while (!= 0);
		POP(EAX);
		POP(ECX);
		POP(GS);
		asmout("JMP next_command");
//	}
}

void GAPI_line()
{
	int *cmd == FS:EBX;
	GAPI_WORK *work == ES:0x0000;

	EAX = cmd[4]; /* opt */
	TEST(EAX, 0xffffff0f);
	if (!= 0)
		goto error;

	EAX &= 0x0030;
	if (== 0)
		goto line;

	if (EAX == 0x0020) {
		/* boxfill */
		EBP = cmd[20]; /* y1 */
		ESI = cmd[12]; /* y0 */
		EBP -= ESI;
		IMUL(ESI, work->linebytes);

boxfill:
		EDX = cmd[ 8]; /* x0 */
		EDI = cmd[16]; /* x1 */
	//	ESI += EDX + 0xe0000000;
		LEA(ESI, [ESI + EDX + 0xe0000000]);
		EDI++;
		CL = cmd[ 4]; /* opt */
		AL = cmd[24]; /* color */
		CL &= 0xc0;
		AH = AL;
		EDI -= EDX;
		EDX = (unsigned short) AX;
		EAX <<= 16;
		/* EDI : x方向のサイズ(バイト数) */
		/* EBP : y方向のサイズ(ドット数 - 1) */
		/* ESI : VRAM上のアドレス */
		EBP++;
		EAX |= EDX;
		/* 少し工夫した描画ルーチン */
		/* 縦に描いていく */
		PUSH((offset) cmd);
		if (CL == 0) {
			if ((unsigned) EBP >= 8) {
				TEST(ESI, 0x03);
				if (!= 0) {
					/* 手抜き */
					do {
						ECX = EBP;
						EBX = ESI;
						ECX -= 8;
						if ((unsigned) >= 0) {
							PUSH(EBP);
							EBP = work->linebytes;
							do {
								[DS:ESI +       0] = AL;
								[DS:ESI + EBP * 1] = AL;
								LEA(ESI, [ESI + EBP * 2]);
								[DS:ESI +       0] = AL;
								[DS:ESI + EBP * 1] = AL;
								LEA(ESI, [ESI + EBP * 2]);
								[DS:ESI +       0] = AL;
								[DS:ESI + EBP * 1] = AL;
								LEA(ESI, [ESI + EBP * 2]);
								[DS:ESI +       0] = AL;
								[DS:ESI + EBP * 1] = AL;
								LEA(ESI, [ESI + EBP * 2]);
								ECX -= 8;
							} while ((unsigned) > 0);
							POP(EBP);
						}
						ECX += 8;
						if (!= 0) {
							do {
								[DS:ESI         ] = AL;
								ESI += work->linebytes;
								ECX--;
							} while (!= 0);
						}
						EDI--;
						LEA(ESI, [EBX + 1]);
						if (== 0)
							goto line_fin;
						TEST(ESI, 0x03);
					} while (!= 0);
				}
				EDI -= 4;
				if ((unsigned) >= 0) {
					do {
						ECX = EBP;
						EBX = ESI;
						ECX -= 8;
						if ((unsigned) >= 0) {
							PUSH(EBP);
							EBP = work->linebytes;
							do {
								[DS:ESI +       0] = EAX;
								[DS:ESI + EBP * 1] = EAX;
								LEA(ESI, [ESI + EBP * 2]);
								[DS:ESI +       0] = EAX;
								[DS:ESI + EBP * 1] = EAX;
								LEA(ESI, [ESI + EBP * 2]);
								[DS:ESI +       0] = EAX;
								[DS:ESI + EBP * 1] = EAX;
								LEA(ESI, [ESI + EBP * 2]);
								[DS:ESI +       0] = EAX;
								[DS:ESI + EBP * 1] = EAX;
								LEA(ESI, [ESI + EBP * 2]);
								ECX -= 8;
							} while ((unsigned) > 0);
							POP(EBP);
						}
						ECX += 8;
						if (!= 0) {
							do {
								[DS:ESI         ] = EAX;
								ESI += work->linebytes;
								ECX--;
							} while (!= 0);
						}
						EDI -= 4;
						LEA(ESI, [EBX + 4]);
					} while ((unsigned) >= 0);
				}
				EDI += 4;
				if (!= 0) {
					/* 手抜き */
					do {
						ECX = EBP;
						EBX = ESI;
						ECX -= 8;
						if ((unsigned) >= 0) {
							PUSH(EBP);
							EBP = work->linebytes;
							do {
								[DS:ESI +       0] = AL;
								[DS:ESI + EBP * 1] = AL;
								LEA(ESI, [ESI + EBP * 2]);
								[DS:ESI +       0] = AL;
								[DS:ESI + EBP * 1] = AL;
								LEA(ESI, [ESI + EBP * 2]);
								[DS:ESI +       0] = AL;
								[DS:ESI + EBP * 1] = AL;
								LEA(ESI, [ESI + EBP * 2]);
								[DS:ESI +       0] = AL;
								[DS:ESI + EBP * 1] = AL;
								LEA(ESI, [ESI + EBP * 2]);
								ECX -= 8;
							} while ((unsigned) > 0);
							POP(EBP);
						}
						ECX += 8;
						if (!= 0) {
							do {
								[DS:ESI         ] = AL;
								ESI += work->linebytes;
								ECX--;
							} while (!= 0);
						}
						EDI--;
						LEA(ESI, [EBX + 1]);
					} while (!= 0);
				}
				POP((offset) cmd);
				(offset) cmd += 28;
				asmout("JMP next_command");
			}
		//	if ((unsigned) EBP < 8) {
				TEST(ESI, 0x03);
				if (!= 0) {
					/* 手抜き */
					do {
						ECX = EBP;
						EBX = ESI;
						do {
							[DS:ESI         ] = AL;
							ESI += work->linebytes;
							ECX--;
						} while (!= 0);
						EDI--;
						LEA(ESI, [EBX + 1]);
						if (== 0)
							goto line_fin;
						TEST(ESI, 0x03);
					} while (!= 0);
				}
				do {
					PUSH(EDI);
					EBX = ESI;
					EDI -= 32;
					if ((unsigned) >= 0) {
						do {
							[DS:ESI     ] = EAX;
							[DS:ESI +  4] = EAX;
							[DS:ESI +  8] = EAX;
							[DS:ESI + 12] = EAX;
							[DS:ESI + 16] = EAX;
							[DS:ESI + 20] = EAX;
							[DS:ESI + 24] = EAX;
							[DS:ESI + 28] = EAX;
							ESI += 32;
							EDI -= 32;
						} while ((unsigned) >= 0);
					}
					EDI += 32 - 4;
					if ((signed) >= 0) {
						do {
							[DS:ESI] = EAX;
							ESI += 4;
							EDI -= 4;
						} while ((unsigned) >= 0);
					}
					EDI += 4;
					if (!= 0) {
						do {
							[DS:ESI] = AL;
							ESI++;
							EDI--;
						} while (!= 0);
					}
					ESI = EBX;
					POP(EDI);
					ESI += work->linebytes;
					EBP--;
				} while (!= 0);
				POP((offset) cmd);
				(offset) cmd += 28;
				asmout("JMP next_command");
	//		}
		}
		if (CL == 0xc0) { /* xor */
			if ((unsigned) EBP >= 8) {
				TEST(ESI, 0x03);
				if (!= 0) {
					/* 手抜き */
					do {
						PUSH(EBP);
						EBX = ESI;
						EBP -= 8;
						if ((unsigned) >= 0) {
							PUSH(EBX);
							EBX = work->linebytes;
							do {
								CL = [DS:ESI +       0];	DL = [DS:ESI + EBX * 1];
								CL ^= AL;					DL ^= AL;
								[DS:ESI +       0] = CL;	[DS:ESI + EBX * 1] = DL;
								LEA(ESI, [ESI + EBX * 2]);
								CL = [DS:ESI +       0];	DL = [DS:ESI + EBX * 1];
								CL ^= AL;					DL ^= AL;
								[DS:ESI +       0] = CL;	[DS:ESI + EBX * 1] = DL;
								LEA(ESI, [ESI + EBX * 2]);
								CL = [DS:ESI +       0];	DL = [DS:ESI + EBX * 1];
								CL ^= AL;					DL ^= AL;
								[DS:ESI +       0] = CL;	[DS:ESI + EBX * 1] = DL;
								LEA(ESI, [ESI + EBX * 2]);
								CL = [DS:ESI +       0];	DL = [DS:ESI + EBX * 1];
								CL ^= AL;					DL ^= AL;
								[DS:ESI +       0] = CL;	[DS:ESI + EBX * 1] = DL;
								LEA(ESI, [ESI + EBX * 2]);
								EBP -= 8;
							} while ((unsigned) > 0);
							POP(EBX);
						}
						EBP += 8;
						if (!= 0) {
							do {
								[DS:ESI         ] ^= AL;
								ESI += work->linebytes;
								EBP--;
							} while (!= 0);
						}
						EDI--;
						LEA(ESI, [EBX + 1]);
						POP(EBP);
						if (== 0)
							goto line_fin;
						TEST(ESI, 0x03);
					} while (!= 0);
				}
				EDI -= 4;
				if ((unsigned) >= 0) {
					do {
						PUSH(EBP);
						EBX = ESI;
						EBP -= 8;
						if ((unsigned) >= 0) {
							PUSH(EBX);
							EBX = work->linebytes;
							do {
								ECX = [DS:ESI +       0];	EDX = [DS:ESI + EBX * 1];
								ECX ^= EAX;					EDX ^= EAX;
								[DS:ESI +       0] = ECX;	[DS:ESI + EBX * 1] = EDX;
								LEA(ESI, [ESI + EBX * 2]);
								ECX = [DS:ESI +       0];	EDX = [DS:ESI + EBX * 1];
								ECX ^= EAX;					EDX ^= EAX;
								[DS:ESI +       0] = ECX;	[DS:ESI + EBX * 1] = EDX;
								LEA(ESI, [ESI + EBX * 2]);
								ECX = [DS:ESI +       0];	EDX = [DS:ESI + EBX * 1];
								ECX ^= EAX;					EDX ^= EAX;
								[DS:ESI +       0] = ECX;	[DS:ESI + EBX * 1] = EDX;
								LEA(ESI, [ESI + EBX * 2]);
								ECX = [DS:ESI +       0];	EDX = [DS:ESI + EBX * 1];
								ECX ^= EAX;					EDX ^= EAX;
								[DS:ESI +       0] = ECX;	[DS:ESI + EBX * 1] = EDX;
								LEA(ESI, [ESI + EBX * 2]);
								EBP -= 8;
							} while ((unsigned) > 0);
							POP(EBX);
						}
						EBP += 8;
						if (!= 0) {
							do {
								[DS:ESI         ] ^= EAX;
								ESI += work->linebytes;
								EBP--;
							} while (!= 0);
						}
						POP(EBP);
						EDI -= 4;
						LEA(ESI, [EBX + 4]);
					} while ((unsigned) >= 0);
				}
				EDI += 4;
				if (!= 0) {
					/* 手抜き */
					do {
						PUSH(EBP);
						EBX = ESI;
						EBP -= 8;
						if ((unsigned) >= 0) {
							PUSH(EBX);
							EBX = work->linebytes;
							do {
								CL = [DS:ESI +      0];	DL = [DS:ESI + EBX * 1];
								CL ^= AL;					DL ^= AL;
								[DS:ESI +       0] = CL;	[DS:ESI + EBX * 1] = DL;
								LEA(ESI, [ESI + EBX * 2]);
								CL = [DS:ESI +      0];	DL = [DS:ESI + EBX * 1];
								CL ^= AL;					DL ^= AL;
								[DS:ESI +       0] = CL;	[DS:ESI + EBX * 1] = DL;
								LEA(ESI, [ESI + EBX * 2]);
								CL = [DS:ESI +      0];	DL = [DS:ESI + EBX * 1];
								CL ^= AL;					DL ^= AL;
								[DS:ESI +       0] = CL;	[DS:ESI + EBX * 1] = DL;
								LEA(ESI, [ESI + EBX * 2]);
								CL = [DS:ESI +      0];	DL = [DS:ESI + EBX * 1];
								CL ^= AL;					DL ^= AL;
								[DS:ESI +       0] = CL;	[DS:ESI + EBX * 1] = DL;
								LEA(ESI, [ESI + EBX * 2]);
								EBP -= 8;
							} while ((unsigned) > 0);
							POP(EBX);
						}
						EBP += 8;
						if (!= 0) {
							do {
								[DS:ESI         ] ^= AL;
								ESI += work->linebytes;
								EBP--;
							} while (!= 0);
						}
						EDI--;
						POP(EBP);
						LEA(ESI, [EBX + 1]);
					} while (!= 0);
				}
				POP((offset) cmd);
				(offset) cmd += 28;
				asmout("JMP next_command");
			}
		//	if ((unsigned) EBP < 8) {
				TEST(ESI, 0x03);
				if (!= 0) {
					/* 手抜き */
					do {
						ECX = EBP;
						EBX = ESI;
						do {
							[DS:ESI         ] ^= AL;
							ESI += work->linebytes;
							ECX--;
						} while (!= 0);
						EDI--;
						LEA(ESI, [EBX + 1]);
						if (== 0)
							goto line_fin;
						TEST(ESI, 0x03);
					} while (!= 0);
				}
				do {
					PUSH(EDI);
					EBX = ESI;
					EDI -= 32;
					if ((unsigned) >= 0) {
						do {
							ECX = [DS:ESI     ];	EDX = [DS:ESI +  4];
							ECX ^= EAX;				EDX ^= EAX;
							[DS:ESI     ] = ECX;	[DS:ESI +  4] = EDX;
							ECX = [DS:ESI +  8];	EDX = [DS:ESI + 12];
							ECX ^= EAX;				EDX ^= EAX;
							[DS:ESI +  8] = ECX;	[DS:ESI + 12] = EDX;
							ECX = [DS:ESI + 16];	EDX = [DS:ESI + 20];
							ECX ^= EAX;				EDX ^= EAX;
							[DS:ESI + 16] = ECX;	[DS:ESI + 20] = EDX;
							ECX = [DS:ESI + 24];	EDX = [DS:ESI + 28];
							ECX ^= EAX;				EDX ^= EAX;
							[DS:ESI + 24] = ECX;	[DS:ESI + 28] = EDX;
							ESI += 32;
							EDI -= 32;
						} while ((unsigned) >= 0);
					}
					EDI += 32 - 4;
					if ((signed) >= 0) {
						do {
							[DS:ESI] ^= EAX;
							ESI += 4;
							EDI -= 4;
						} while ((unsigned) >= 0);
					}
					EDI += 4;
					if (!= 0) {
						do {
							[DS:ESI] ^= AL;
							ESI++;
							EDI--;
						} while (!= 0);
					}
					ESI = EBX;
					POP(EDI);
					ESI += work->linebytes;
					EBP--;
				} while (!= 0);
				POP((offset) cmd);
				(offset) cmd += 28;
				asmout("JMP next_command");
	//		}
		}
		if (CL == 0x40) { /* and */
	//		if ((unsigned) EBP >= 8) {
				TEST(ESI, 0x03);
				if (!= 0) {
					/* 手抜き */
					do {
						PUSH(EBP);
						EBX = ESI;
						EBP -= 8;
						if ((unsigned) >= 0) {
							PUSH(EBX);
							EBX = work->linebytes;
							do {
								CL = [DS:ESI +       0];	DL = [DS:ESI + EBX * 1];
								CL &= AL;					DL &= AL;
								[DS:ESI +       0] = CL;	[DS:ESI + EBX * 1] = DL;
								LEA(ESI, [ESI + EBX * 2]);
								CL = [DS:ESI +       0];	DL = [DS:ESI + EBX * 1];
								CL &= AL;					DL &= AL;
								[DS:ESI +       0] = CL;	[DS:ESI + EBX * 1] = DL;
								LEA(ESI, [ESI + EBX * 2]);
								CL = [DS:ESI +       0];	DL = [DS:ESI + EBX * 1];
								CL &= AL;					DL &= AL;
								[DS:ESI +       0] = CL;	[DS:ESI + EBX * 1] = DL;
								LEA(ESI, [ESI + EBX * 2]);
								CL = [DS:ESI +       0];	DL = [DS:ESI + EBX * 1];
								CL &= AL;					DL &= AL;
								[DS:ESI +       0] = CL;	[DS:ESI + EBX * 1] = DL;
								LEA(ESI, [ESI + EBX * 2]);
								EBP -= 8;
							} while ((unsigned) > 0);
							POP(EBX);
						}
						EBP += 8;
						if (!= 0) {
							do {
								[DS:ESI         ] &= AL;
								ESI += work->linebytes;
								EBP--;
							} while (!= 0);
						}
						EDI--;
						LEA(ESI, [EBX + 1]);
						POP(EBP);
						if (== 0)
							goto line_fin;
						TEST(ESI, 0x03);
					} while (!= 0);
				}
				EDI -= 4;
				if ((unsigned) >= 0) {
					do {
						PUSH(EBP);
						EBX = ESI;
						EBP -= 8;
						if ((unsigned) >= 0) {
							PUSH(EBX);
							EBX = work->linebytes;
							do {
								ECX = [DS:ESI +       0];	EDX = [DS:ESI + EBX * 1];
								ECX &= EAX;					EDX &= EAX;
								[DS:ESI +       0] = ECX;	[DS:ESI + EBX * 1] = EDX;
								LEA(ESI, [ESI + EBX * 2]);
								ECX = [DS:ESI +       0];	EDX = [DS:ESI + EBX * 1];
								ECX &= EAX;					EDX &= EAX;
								[DS:ESI +       0] = ECX;	[DS:ESI + EBX * 1] = EDX;
								LEA(ESI, [ESI + EBX * 2]);
								ECX = [DS:ESI +       0];	EDX = [DS:ESI + EBX * 1];
								ECX &= EAX;					EDX &= EAX;
								[DS:ESI +       0] = ECX;	[DS:ESI + EBX * 1] = EDX;
								LEA(ESI, [ESI + EBX * 2]);
								ECX = [DS:ESI +       0];	EDX = [DS:ESI + EBX * 1];
								ECX &= EAX;					EDX &= EAX;
								[DS:ESI +       0] = ECX;	[DS:ESI + EBX * 1] = EDX;
								LEA(ESI, [ESI + EBX * 2]);
								EBP -= 8;
							} while ((unsigned) > 0);
							POP(EBX);
						}
						EBP += 8;
						if (!= 0) {
							do {
								[DS:ESI         ] &= EAX;
								ESI += work->linebytes;
								EBP--;
							} while (!= 0);
						}
						POP(EBP);
						EDI -= 4;
						LEA(ESI, [EBX + 4]);
					} while ((unsigned) >= 0);
				}
				EDI += 4;
				if (!= 0) {
					/* 手抜き */
					do {
						PUSH(EBP);
						EBX = ESI;
						EBP -= 8;
						if ((unsigned) >= 0) {
							PUSH(EBX);
							EBX = work->linebytes;
							do {
								CL = [DS:ESI +       0];	DL = [DS:ESI + EBX * 1];
								CL &= AL;					DL &= AL;
								[DS:ESI +       0] = CL;	[DS:ESI + EBX * 1] = DL;
								LEA(ESI, [ESI + EBX * 2]);
								CL = [DS:ESI +       0];	DL = [DS:ESI + EBX * 1];
								CL &= AL;					DL &= AL;
								[DS:ESI +       0] = CL;	[DS:ESI + EBX * 1] = DL;
								LEA(ESI, [ESI + EBX * 2]);
								CL = [DS:ESI +       0];	DL = [DS:ESI + EBX * 1];
								CL &= AL;					DL &= AL;
								[DS:ESI +       0] = CL;	[DS:ESI + EBX * 1] = DL;
								LEA(ESI, [ESI + EBX * 2]);
								CL = [DS:ESI +       0];	DL = [DS:ESI + EBX * 1];
								CL &= AL;					DL &= AL;
								[DS:ESI +       0] = CL;	[DS:ESI + EBX * 1] = DL;
								LEA(ESI, [ESI + EBX * 2]);
								EBP -= 8;
							} while ((unsigned) > 0);
							POP(EBX);
						}
						EBP += 8;
						if (!= 0) {
							do {
								[DS:ESI         ] &= AL;
								ESI += work->linebytes;
								EBP--;
							} while (!= 0);
						}
						EDI--;
						POP(EBP);
						LEA(ESI, [EBX + 1]);
					} while (!= 0);
				}
	//		}
			POP((offset) cmd);
			(offset) cmd += 28;
			asmout("JMP next_command");
		}
//		if (CL == 0x80) { /* or */
	//		if (EBP >= 8) {
				TEST(ESI, 0x03);
				if (!= 0) {
					/* 手抜き */
					do {
						PUSH(EBP);
						EBX = ESI;
						EBP -= 8;
						if ((unsigned) >= 0) {
							PUSH(EBX);
							EBX = work->linebytes;
							do {
								CL = [DS:ESI +       0];	DL = [DS:ESI + EBX * 1];
								CL |= AL;					DL |= AL;
								[DS:ESI +       0] = CL;	[DS:ESI + EBX * 1] = DL;
								LEA(ESI, [ESI + EBX * 2]);
								CL = [DS:ESI +       0];	DL = [DS:ESI + EBX * 1];
								CL |= AL;					DL |= AL;
								[DS:ESI +       0] = CL;	[DS:ESI + EBX * 1] = DL;
								LEA(ESI, [ESI + EBX * 2]);
								CL = [DS:ESI +       0];	DL = [DS:ESI + EBX * 1];
								CL |= AL;					DL |= AL;
								[DS:ESI +       0] = CL;	[DS:ESI + EBX * 1] = DL;
								LEA(ESI, [ESI + EBX * 2]);
								CL = [DS:ESI +       0];	DL = [DS:ESI + EBX * 1];
								CL |= AL;					DL |= AL;
								[DS:ESI +       0] = CL;	[DS:ESI + EBX * 1] = DL;
								LEA(ESI, [ESI + EBX * 2]);
								EBP -= 8;
							} while ((unsigned) > 0);
							POP(EBX);
						}
						EBP += 8;
						if (!= 0) {
							do {
								[DS:ESI         ] |= AL;
								ESI += work->linebytes;
								EBP--;
							} while (!= 0);
						}
						EDI--;
						LEA(ESI, [EBX + 1]);
						POP(EBP);
						if (== 0)
							goto line_fin;
						TEST(ESI, 0x03);
					} while (!= 0);
				}
				EDI -= 4;
				if ((unsigned) >= 0) {
					do {
						PUSH(EBP);
						EBX = ESI;
						EBP -= 8;
						if ((unsigned) >= 0) {
							PUSH(EBX);
							EBX = work->linebytes;
							do {
								ECX = [DS:ESI +       0];	EDX = [DS:ESI + EBX * 1];
								ECX |= EAX;					EDX |= EAX;
								[DS:ESI +       0] = ECX;	[DS:ESI + EBX * 1] = EDX;
								LEA(ESI, [ESI + EBX * 2]);
								ECX = [DS:ESI +       0];	EDX = [DS:ESI + EBX * 1];
								ECX |= EAX;					EDX |= EAX;
								[DS:ESI +       0] = ECX;	[DS:ESI + EBX * 1] = EDX;
								LEA(ESI, [ESI + EBX * 2]);
								ECX = [DS:ESI +       0];	EDX = [DS:ESI + EBX * 1];
								ECX |= EAX;					EDX |= EAX;
								[DS:ESI +       0] = ECX;	[DS:ESI + EBX * 1] = EDX;
								LEA(ESI, [ESI + EBX * 2]);
								ECX = [DS:ESI +       0];	EDX = [DS:ESI + EBX * 1];
								ECX |= EAX;					EDX |= EAX;
								[DS:ESI +       0] = ECX;	[DS:ESI + EBX * 1] = EDX;
								LEA(ESI, [ESI + EBX * 2]);
								EBP -= 8;
							} while ((unsigned) > 0);
							POP(EBX);
						}
						EBP += 8;
						if (!= 0) {
							do {
								[DS:ESI         ] |= EAX;
								ESI += work->linebytes;
								EBP--;
							} while (!= 0);
						}
						POP(EBP);
						EDI -= 4;
						LEA(ESI, [EBX + 4]);
					} while ((unsigned) >= 0);
				}
				EDI += 4;
				if (!= 0) {
					/* 手抜き */
					do {
						PUSH(EBP);
						EBX = ESI;
						EBP -= 8;
						if ((unsigned) >= 0) {
							PUSH(EBX);
							EBX = work->linebytes;
							do {
								CL = [DS:ESI +       0];	DL = [DS:ESI + EBX * 1];
								CL |= AL;					DL |= AL;
								[DS:ESI +       0] = CL;	[DS:ESI + EBX * 1] = DL;
								LEA(ESI, [ESI + EBX * 2]);
								CL = [DS:ESI +       0];	DL = [DS:ESI + EBX * 1];
								CL |= AL;					DL |= AL;
								[DS:ESI +       0] = CL;	[DS:ESI + EBX * 1] = DL;
								LEA(ESI, [ESI + EBX * 2]);
								CL = [DS:ESI +       0];	DL = [DS:ESI + EBX * 1];
								CL |= AL;					DL |= AL;
								[DS:ESI +       0] = CL;	[DS:ESI + EBX * 1] = DL;
								LEA(ESI, [ESI + EBX * 2]);
								CL = [DS:ESI +       0];	DL = [DS:ESI + EBX * 1];
								CL |= AL;					DL |= AL;
								[DS:ESI +       0] = CL;	[DS:ESI + EBX * 1] = DL;
								LEA(ESI, [ESI + EBX * 2]);
								EBP -= 8;
							} while ((unsigned) > 0);
							POP(EBX);
						}
						EBP += 8;
						if (!= 0) {
							do {
								[DS:ESI         ] |= AL;
								ESI += work->linebytes;
								EBP--;
							} while (!= 0);
						}
						EDI--;
						POP(EBP);
						LEA(ESI, [EBX + 1]);
					} while (!= 0);
				}
	//		}
line_fin:
			POP((offset) cmd);
			(offset) cmd += 28;
			asmout("JMP next_command");
//		}


	}

	/* box */
	EBP = cmd[20]; // y1
	ESI = cmd[12]; // y0
	EBP -= ESI;
	IMUL(ESI, work->linebytes);
	if ((unsigned) EBP <= 1)
		goto boxfill;
	PUSH(ESI);
	EDX = cmd[ 8]; // x0
	EDI = cmd[16]; // x1
//	ESI += EDX + 0xe0000000;
	LEA(ESI, [ESI + EDX + 0xe0000000]);
	EDI++;
	CL = cmd[ 4]; // opt
	AL = cmd[24]; // color
	CL &= 0xc0;
	EDI -= EDX;
	/* EDI : x方向のサイズ(バイト数) */
	/* EBP : y方向のサイズ(ドット数 - 1) */
	/* ESI : VRAM上のアドレス */
	EBP--;
	EDX = cmd[20];
	IMUL(EDX, work->linebytes);
	EDX += cmd[ 8];
	EDX += 0xe0000000;
	if (CL == 0) { /* pset */
		/* 全く工夫のない描画ルーチン */
		ECX = ESI;
		do {
			[DS:ESI] = AL;
			ESI++;
			[DS:EDX] = AL;
			EDX++;
			EDI--;
		} while (!= 0);
		POP(EDI);
		ECX += work->linebytes;
		EDI += cmd[16];
		EDI += 0xe0000000;
		EDI += work->linebytes;
		do {
			[DS:ECX] = AL;
			ECX += work->linebytes;
			[DS:EDI] = AL;
			EDI += work->linebytes;
			EBP--;
		} while (!= 0);
		(offset) cmd += 28;
		asmout("JMP next_command");
	}
	if (CL == 0xc0) { /* xor */
		/* 全く工夫のない描画ルーチン */
		ECX = ESI;
		do {
			[DS:ESI] ^= AL;
			ESI++;
			[DS:EDX] ^= AL;
			EDX++;
			EDI--;
		} while (!= 0);
		POP(EDI);
		ECX += work->linebytes;
		EDI += cmd[16];
		EDI += 0xe0000000;
		EDI += work->linebytes;
		do {
			[DS:ECX] ^= AL;
			ECX += work->linebytes;
			[DS:EDI] ^= AL;
			EDI += work->linebytes;
			EBP--;
		} while (!= 0);
		(offset) cmd += 28;
		asmout("JMP next_command");
	}
	if (CL == 0x40) { /* and */
		/* 全く工夫のない描画ルーチン */
		ECX = ESI;
		do {
			[DS:ESI] &= AL;
			ESI++;
			[DS:EDX] &= AL;
			EDX++;
			EDI--;
		} while (!= 0);
		POP(EDI);
		ECX += work->linebytes;
		EDI += cmd[16];
		EDI += 0xe0000000;
		EDI += work->linebytes;
		do {
			[DS:ECX] &= AL;
			ECX += work->linebytes;
			[DS:EDI] &= AL;
			EDI += work->linebytes;
			EBP--;
		} while (!= 0);
		(offset) cmd += 28;
		asmout("JMP next_command");
	}
//	if (CL == 0x80) { /* or */
		/* 全く工夫のない描画ルーチン */
		ECX = ESI;
		do {
			[DS:ESI] |= AL;
			ESI++;
			[DS:EDX] |= AL;
			EDX++;
			EDI--;
		} while (!= 0);
		POP(EDI);
		ECX += work->linebytes;
		EDI += cmd[16];
		EDI += 0xe0000000;
		EDI += work->linebytes;
		do {
			[DS:ECX] |= AL;
			ECX += work->linebytes;
			[DS:EDI] |= AL;
			EDI += work->linebytes;
			EBP--;
		} while (!= 0);
		(offset) cmd += 28;
		asmout("JMP next_command");
//	}

line:
	(offset) cmd += 28;
	asmout("JMP next_command");

error:
	INT(0x03);
}
