aboutsummaryrefslogtreecommitdiff
path: root/screen-to-xpm.c
blob: cf29e01b827b0c9164549aba555dd8278f2ddfab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include <stdio.h>
#include <string.h>

#include "packet.h"


#define IMAGE_HEADER_BYTES_BW   40
#define IMAGE_HEADER_BYTES_COL  41
#define HEADER_SIZE             3
#define IMAGE_WIDTH             128
#define IMAGE_HEIGHT            64
#define NUM_COLOURS             3

#define COLOUR_BLANK            '0'

const char colours[] = {'B', 'G', 'R'};


void load_mono(char (*image)[IMAGE_WIDTH][IMAGE_HEIGHT])
{
	unsigned short x, y;
	char c;
	char i;
	for (x = 0; x < IMAGE_WIDTH && !feof(stdin); x+=8)
	{
		for (y = 0; y < IMAGE_HEIGHT && !feof(stdin); y++)
		{
			c = fgetc(stdin);
			for (i = 0; i < 8; i++)
				(*image)[x+i][y] = c & (1<<(i))? colours[0] : COLOUR_BLANK;
		}
	}
}

void load_colour(char (*image)[IMAGE_WIDTH][IMAGE_HEIGHT])
{
	short x, y, colour;
	char buffer[IMAGE_WIDTH/8][IMAGE_HEIGHT];
	char c;
	char i;
	for (colour = 0; colour < NUM_COLOURS; colour++)
	{
		fread(buffer, sizeof(buffer), 1, stdin);
		for (x = 0; x < IMAGE_WIDTH && !feof(stdin); x+=8)
		{
			for (y = 0; y < IMAGE_HEIGHT && !feof(stdin); y++)
			{
				c = buffer[x/8][IMAGE_HEIGHT-1-y];
				for (i = 0; i < 8; i++)
				{
					if ((*image)[x+i][y] == COLOUR_BLANK)
						(*image)[x+i][y] = c & (1<<(i))? colours[colour] : COLOUR_BLANK;
				}
			}
		}
		/* eat the checksum */
		fgetc(stdin);
		
		/* eat the : and the colour identification bytes if another channel remains */
		if (colour != NUM_COLOURS-1)
		{
			fgetc(stdin);
			fgetc(stdin);
		}
	}
}



int main(int argc, char **argv)
{
	unsigned char header[PKT_HEADER_MAX_SIZE];
	char image[IMAGE_WIDTH][IMAGE_HEIGHT];
	int x, y, read, expected;
	enum packet_types type;

	if (argc != 1)
	{
		fprintf(stderr,
			"Converts CASIO (C)FX-9850 screen dumps to XPM images.\n"
			"Reads raw screen dump packets from stdin and outputs XPM to stdout\n"
			"Information and warning messages printed to stderr when necessary\n"
			"\n"
			"Syntax: %s < screen.dump > screen.xpm\n", argv[0]);
		return 1;
	}

	/* Lazy here, we just catch EOF later */
	/* magic number: 3 == strlen(":DD") == strlen(":DC") */
	read = fread(header, 3, 1, stdin);

	switch (get_packet_type(header))
	{
		case PKT_SCREEN_HEADER_BW:
			type = PKT_SCREEN_HEADER_BW;
			expected = IMAGE_HEADER_BYTES_BW;
			break;
		case PKT_SCREEN_HEADER_COL:
			type = PKT_SCREEN_HEADER_COL;
			expected = IMAGE_HEADER_BYTES_COL;
			break;
		default:
			fprintf(stderr, "Invalid header '%s', not a Casio FX 9850 screenshot\n", header);
			return 1;
			break;
	}

	fprintf(stderr, "Detected %s screenshot\n",
		type == PKT_SCREEN_HEADER_BW? "monochrome" : "colour");

	/* skip over rest of header */
	expected -= read;
	while (--expected)
		fgetc(stdin);

	memset(image, COLOUR_BLANK, sizeof(image));

	if (type == PKT_SCREEN_HEADER_BW)
		load_mono(&image);
	else 
		load_colour(&image);

	/* Tasty! A hard-coded XPM header! */
	printf(	"/* XPM */\n"
			"static char *casio_screenshot[] = {\n"
			"	\"%d %d 4 1\",\n"
			"	\"B c #000033\",\n"
			"	\"G c #005555\",\n"
			"	\"R c #FF6633\",\n"
			"	\"0 c #FFFFFF\",\n",
			IMAGE_WIDTH,IMAGE_HEIGHT
	);

	for (y = 0; y < IMAGE_HEIGHT; y++)
	{
		printf("\""); /* XPM stuff */

		for (x = IMAGE_WIDTH-1; x >= 0; x--)
			printf("%c",image[x][y]);

		printf("\",\n"); /* Again, XPM stuff */
	}


	/* Hard-coded XPM footer */
	printf("};");

	return 0;
}