#define DRAW_ENABLE_VISUAL   		1
#define DRAW_ENABLE_PRIORITY 		2
#define DRAW_ENABLE_CONTROL 		4

#define PATTERN_FLAG_RECTANGLE		0x10
#define PATTERN_FLAG_USE_PATTERN	0x20
      
#define asVISUAL					0
#define asPRIORITY					1
#define asCONTROL					2
#define asEXXO						3

#define PIC_WIDTH					320
#define PIC_HEIGHT					200

#define PIC_SIZE					(320*200)


typedef struct {
	int x,y;
} sPOINT;

/*****************************************************************************/
U8 palDefault[40] = {
	0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
	0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0x88,
	0x88, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x88,
	0x88, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
	0x08, 0x91, 0x2a, 0x3b, 0x4c, 0x5d, 0x6e, 0x88
};

U8 priTable[40];

/*****************************************************************************/
U8 *buf,*ptr;


/*****************************************************************************/
S8 PeekInput() {
	return *ptr;
}
/*****************************************************************************/
S8 GetInput() 
{
	return *ptr++;
}
/*****************************************************************************/
void SkipInput(int amount) 
{
	ptr +=	amount;
}
/*****************************************************************************/
sPOINT GetAbsCoordinates()
{
	sPOINT s;
	int coordinate_prefix;	
	
	s.x = get_input() | (coordinate_prefix & 0xf0) << 4;
	s.y = get_input() | (coordinate_prefix & 0x0f) << 8;
	
	return s;
}
/*****************************************************************************/
sPOINT GetRelCoordinates(int x, int y)
{
	sPOINT s;
	int input;	
	
	input = get_input();
	if (input & 0x80)
		x -= (input >> 4);
	else
		x += (input >> 4);

	if(input & 0x08)
		y -= (input & 0x7);
	else
		y += (input & 0x7);

	s.x = x;
	s.y = y;
	
	return s;
}
/*****************************************************************************/
void DrawPic(BOOL CUMULATIVE, BOOL FILL_IN_BLACK, int defaultPalette, U8 **bitmaps)
{
	U8 palette[4][40];
	int drawenable,priority,col1,col2,pattern_nr,pattern_code,code;
	sPOINT coords,oldCoords;
	
	for(int i=0;i<4;i++)
		memcpy(palette[i],palDefault,sizeof(palDefault));
		
	drawenable = DRAW_ENABLE_VISUAL | DRAW_ENABLE_PRIORITY;
	priority = 0;
	col1 = col2 = 0;
	pattern_nr = 0;
	pattern_code = 0;

	if (!CUMULATIVE) {
		memset(bitmaps[asVISUAL],0xF,PIC_SIZE);
		for(int i=1;i<4;i++)
			memset(bitmaps[i],0,PIC_SIZE);
	}

	for(;;) {
		switch(get_input()) {
			case 0xf0: /* PIC_OP_SET_COLOR */
				code = get_input();
				col1 = palette[default_palette](code / 40)];
				col2 = palette[default_palette](code % 40)];
				drawenable |= DRAW_ENABLE_VISUAL;
				break;
			case 0xf1: /* PIC_OP_DISABLE_VISUAL */
				drawenable &= ~DRAW_ENABLE_VISUAL;
				break;
			case 0xf2 : /* PIC_OP_SET_PRIORITY */
				code = get_input();
				priority = code & 0xf;
				drawenable |= DRAW_ENABLE_PRIORITY;
				break;
			case 0xf3: /* PIC_OP_DISABLE_PRIORITY */
				drawenable &= ~DRAW_ENABLE_PRIORITY;
				break;
			case 0xf4: /* PIC_OP_RELATIVE_PATTERNS */
				if(pattern_code & PATTERN_FLAG_USE_PATTERN)
					pattern_nr = (get_input() >> 1) & 0x7f;
					
				coords = GetAbsCoordinates();

				DrawPattern(coords.x, coords.y, col1, col2, priority, control, drawenable,
						 pattern_code & PATTERN_FLAG_USE_PATTERN,
						 pattern_size, pattern_nr, pattern_code & PATTERN_FLAG_RECTANGLE);

				while (peek_input() < 0xf0) {
					if (pattern_code & PATTERN_FLAG_USE_PATTERN) {
						pattern_nr = (get_input() >> 1) & 0x7f
					}
					coords = GetRelCoordinates(x,y);
					DrawPattern(coords.x, coords.y, col1, col2, priority, control, drawenable,
							 pattern_code & PATTERN_FLAG_USE_PATTERN,
							 pattern_size, pattern_nr, pattern_code & PATTERN_FLAG_RECTANGLE);
				}
				break;
			case 0xf5: /* PIC_OP_RELATIVE_MEDIUM_LINES */
				coords = GetAbsCoordinates();
				while (peek_input() < 0xf0) {
					temp = get_input();
					if (temp & 0x80)
						y = oldCoords.y - (temp & 0x7f);
					else
						y = oldCoords.y + temp;
						
					x = oldCoords.x + get_input();
					DitherLine(oldCoords.x, oldCoords.y, x, y, col1, col2, priority, special, drawenable);
					oldCoords = coords;
				}
				break;
			case 0xf6: /* PIC_OP_RELATIVE_LONG_LINES */
				oldCoords =  GetAbsCoordinates()
				while (peek_input() < 0xf0) {
					coords = GetAbsCoordinates();
					DitherLine(oldCoords.x, oldCoords.y, x, y, col1, col2, priority, special, drawenable);
					oldCoords = coords;
				}
				break;
			case 0xf7: /* PIC_OP_RELATIVE_SHORT_LINES */
				oldCoords =  GetAbsCoordinates()
				while (peek_input() < 0xf0) {
					coords = GetRelCoordinates(oldCoords.x, oldCoords.y);
					DitherLine(oldCoords.x, oldCoords.y, x, y, col1, col2, priority, special, drawenable);
					oldCoords = coords;
				}
				break;
			case 0xf8: /* PIC_OP_FILL */
				while (peek_unput() < 0xf0) {
					coords = GetAbsCoordinates();
					DitherFill(coords.x, coords.y, col1, col2, priority, special, drawenable);
				}
				break;
			case 0xf9: /* PIC_OP_SET_PATTERN */
				pattern_code = get_input() & 0x37;
				pattern_size = pattern_code & 0x7;
				break;
			case 0xfa: /* PIC_OP_ABSOLUTE_PATTERNS */
				while (peek_input() < 0xf0) {
					if (pattern_code & PATTERN_FLAG_USE_PATTERN)
						pattern_nr = (get_input() >> 1) & 0x7f;
					
					coords = GetAbsCoordinates();
					DrawPattern(coords.x, coords.y, col1, col2, priority, control, drawenable,
							 pattern_code & PATTERN_FLAG_USE_PATTERN,
							 pattern_size, pattern_nr, pattern_code & PATTERN_FLAG_RECTANGLE);
				}
				break;
			case 0xfb: /* PIC_OP_SET_CONTROL */
				control = get_input() & 0x0f;
				drawenable |= DRAW_ENABLE_CONTROL;
				break;
			case 0xfc: /* PIC_OP_DISABLE_CONTROL */
				drawenable &= ~DRAW_ENABLE_CONTROL;
				break;
			case 0xfd: /* PIC_OP_RELATIVE_MEDIUM_PATTERNS */
				if (pattern_code & PATTERN_FLAG_USE_PATTERN)
					pattern_nr = (get_input() >> 1) & 0x7f;
				

				oldCoords =  GetAbsCoordinates();

				DrawPattern(coords.x, coords.y, col1, col2, priority, control, drawenable,
						 pattern_code & PATTERN_FLAG_USE_PATTERN,
						 pattern_size, pattern_nr, pattern_code & PATTERN_FLAG_RECTANGLE);

				while (peek_input() < 0xf0) {
					if (pattern_code & PATTERN_FLAG_USE_PATTERN)
						pattern_nr = (get_input() >> 1) & 0x7f;
			
					temp = get_input();
					if (temp & 0x80)
						y = oldCoords.y - (temp & 0x7f);
					else
						y = oldCoords.y + temp;
					
					x = oldCoords.x + get_input();
					DrawPattern(coords.x, coords.y, col1, col2, priority, control, drawenable,
							 pattern_code & PATTERN_FLAG_USE_PATTERN,
							 pattern_size, pattern_nr, pattern_code & PATTERN_FLAG_RECTANGLE);
				}
				break;
			case 0xfd: /* PIC_OP_OPX */
				switch(get_input()) {
					case 0x00: /* PIC_OPX_SET_PALETTE_ENTRY */
						while(peek_input() < 0xf0) {
							index = get_input();
							color = get_input();
							palette[index / 40][color % 40] = color;
						}
						break;

					case 0x01: /* PIC_OPX_SET_PALETTE */
						palette_number = get_input();
						for(i = 0; i <40; i++)
							palette[palette_number][i] = get_input();
						break;

					case 0x02: /* PIC_OPX_MONO0 */
						skip_input(41);
						break;

					case 0x03: /* PIC_OPX_MONO1 */
						skip_input(1);
						break;

					case 0x04: /* PIC_OPX_MONO2 */
					case 0x05: /* PIC_OPX_MONO3 */
						skip_input(1);
						break;

					case 0x06: /* PIC_OPX_MONO4 */
					case 0x07: /* PIC_OPX_EMBEDDED_VIEW */ /* SCI01 operation */
					case 0x08: /* PIC_OPX_SET_PRIORITY_TABLE */ /* SCI01 operation */
						break;
				}
				break;
			case 0xff: return;
		}
	}
}
/*****************************************************************************/

