1 /*
2 * lcdtest: LCD monitor test pattern generator
3 *
4 * Main program
5 * $Id: lcdtest.c 44 2010-01-26 06:28:14Z eric $
6 * Copyright 2005, 2007, 2010 Eric Smith <eric@brouhaha.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 3 as
10 * published by the Free Software Foundation. Note that permission is
11 * not granted to redistribute this program under the terms of any
12 * other version of the General Public License.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23
24 #include <stdarg.h>
25 #include <stdbool.h>
26 #include <stddef.h>
27 #include <stdint.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31
32 #include <SDL/SDL.h>
33 #include <SDL/SDL_image.h>
34 #include <SDL/SDL_ttf.h>
35
36 #define UNUSED __attribute__ ((unused))
37
38 #define QMAKESTR(x) #x
39 #define MAKESTR(x) QMAKESTR(x)
40
41 char *progname;
42
43
44 const char help_teaser_message [] =
45 {
46 "press / or ? for help"
47 };
48
49 const char help_message [] =
50 {
51 "commands:\n"
52 " Change foreground color:\n"
53 " r: red w: white\n"
54 " g: green k: black\n"
55 " b: blue\n"
56 " Change pattern:\n"
57 " s: solid fill h: horizontal lines\n"
58 " c: crosshatch v: vertical lines\n"
59 " d: dots x: diagonal crosshatch\n"
60 " a: white vertical lines with two pixel pitch\n"
61 " arrow keys: move lines in arrow direction\n"
62 " plus: increase spacing between lines\n"
63 " minus: decrease spacing between lines\n"
64 " 0..9: select predefined line spacings\n"
65 " q or Escape: exit program\n"
66 " ? or /: toggle display of help message\n"
67 "\n"
68 "lcdtest " MAKESTR(RELEASE) " Free Software (GPLv3)\n"
69 "Copyright 2005-2010 Eric Smith <eric@brouhaha.com>\n"
70 "http://www.brouhaha.com/~eric/software/lcdtest/"
71 };
72
73
help(FILE * f)74 void help (FILE *f)
75 {
76 fprintf (f, "%s", help_message);
77 }
78
79
usage(FILE * f)80 void usage (FILE *f)
81 {
82 fprintf (f, "lcdtest " MAKESTR(RELEASE) " Copyright 2005-2007 Eric Smith <eric@brouhaha.com>\n");
83 fprintf (f, "http://www.brouhaha.com/~eric/software/lcdtest/");
84 fprintf (f, "\n");
85 fprintf (f, "usage: %s [options]\n", progname);
86 fprintf (f, "options:\n");
87 fprintf (f, " --help show usage and command keys\n");
88 fprintf (f, " --window display in a window rather than full screen\n");
89 fprintf (f, " -x <count> use a video mode with the specified horizontal resolution\n");
90 fprintf (f, " -y <count> use a video mode with the specified vertical resolution\n");
91 fprintf (f, " --list-modes list available video modes (including resolution)\n");
92 }
93
94
fatal(int ret,char * format,...)95 void fatal (int ret, char *format, ...)
96 {
97 va_list ap;
98
99 fprintf (stderr, "fatal error: ");
100 va_start (ap, format);
101 vfprintf (stderr, format, ap);
102 va_end (ap);
103 if (ret == 1)
104 usage (stderr);
105 exit (ret);
106 }
107
108
get_text_size(TTF_Font * font,const char * text,int * width,int * height)109 void get_text_size (TTF_Font *font, const char *text, int *width, int *height)
110 {
111 *width = 0;
112 *height = 0;
113
114 while (*text)
115 {
116 const char *p;
117 int n;
118 int line_width, line_height;
119 char buf [200];
120
121 p = strchr (text, '\n');
122 if (p)
123 {
124 n = p - text;
125 p++;
126 }
127 else
128 {
129 n = strlen (text);
130 p = text + n;
131 }
132
133 if (n > (sizeof (buf) - 1))
134 n = sizeof (buf) - 1;
135 if (n == 0)
136 buf [n++] = ' ';
137 else
138 strncpy (buf, text, n);
139 buf [n] = '\0';
140
141 if (TTF_SizeText (font, buf, & line_width, & line_height) != 0)
142 fatal (2, "TTF_SizeText failed (missing glyph?)\n");
143 *height += line_height;
144 if (line_width > *width)
145 *width = line_width;
146
147 text = p;
148 }
149 }
150
create_text_surface(const char * message,const char * font_path,int font_size,SDL_Color fg,SDL_Color bg UNUSED)151 SDL_Surface *create_text_surface (const char *message,
152 const char *font_path,
153 int font_size,
154 SDL_Color fg,
155 SDL_Color bg UNUSED)
156 {
157 TTF_Font *font;
158 int width, height;
159 SDL_Surface *text_surface;
160 SDL_Rect dest_rect;
161 int line_height;
162
163 if ((! TTF_WasInit ()) && (TTF_Init () != 0))
164 fatal (2, "can't initialize SDL_ttf\n");
165
166 font = TTF_OpenFont (font_path, font_size);
167 if (! font)
168 fatal (2, "can't open font\n");
169
170 line_height = TTF_FontLineSkip (font);
171
172 get_text_size (font, message, & width, & height);
173 printf ("width: %d, height: %d\n", width, height);
174
175 text_surface = SDL_CreateRGBSurface (SDL_HWSURFACE,
176 width,
177 height,
178 32,
179 0x000000ff,
180 0x0000ff00,
181 0x00ff0000,
182 0);
183
184 dest_rect.w = width;
185 dest_rect.h = height;
186 dest_rect.x = 0;
187 dest_rect.y = 0;
188
189 while (*message)
190 {
191 const char *p;
192 int n;
193 SDL_Surface *line_surface;
194 char buf [200];
195
196 p = strchr (message, '\n');
197 if (p)
198 {
199 n = p - message;
200 p++;
201 }
202 else
203 {
204 n = strlen (message);
205 p = message + n;
206 }
207
208 if (n > (sizeof (buf) - 1))
209 n = sizeof (buf) - 1;
210 if (n == 0)
211 buf [n++] = ' ';
212 else
213 strncpy (buf, message, n);
214 buf [n] = '\0';
215
216 if (n)
217 {
218 line_surface = TTF_RenderText_Blended (font, buf, fg);
219 if (! line_surface)
220 fatal (2, "can't render text\n");
221 }
222
223 SDL_BlitSurface (line_surface,
224 & line_surface->clip_rect,
225 text_surface,
226 & dest_rect);
227 SDL_FreeSurface (line_surface);
228
229 dest_rect.y += line_height;
230
231 message = p;
232 }
233
234 TTF_CloseFont (font);
235 return (text_surface);
236 }
237
238
239 typedef struct
240 {
241 uint8_t red;
242 uint8_t green;
243 uint8_t blue;
244 } my_color_t;
245
246 my_color_t test_colors [] =
247 {
248 { 0xff, 0x00, 0x00 },
249 { 0x00, 0xff, 0x00 },
250 { 0x00, 0x00, 0xff },
251 { 0xff, 0xff, 0xff },
252 { 0x80, 0x80, 0x80 },
253 { 0x00, 0x00, 0x00 }
254 };
255
256
257 // For special keys without Unicode codepoints (such as escape and
258 // the cursor keys), we translate to a codepoint in the Unicode
259 // Private Use Area (PUA), from 0xe000 to 0xf8ff.
260 #define PUA_ESCAPE 0xe000
261 #define PUA_UP 0xe001
262 #define PUA_DOWN 0xe002
263 #define PUA_LEFT 0xe003
264 #define PUA_RIGHT 0xe004
265
266
267 // wait for a keypress and return the corresponding Unicode code point
268
wait_key(void)269 wchar_t wait_key (void)
270 {
271 SDL_Event event;
272
273 while (1)
274 {
275 SDL_WaitEvent (& event);
276 switch (event.type)
277 {
278 case SDL_KEYDOWN:
279 switch (event.key.keysym.sym)
280 {
281 case SDLK_ESCAPE:
282 return PUA_ESCAPE;
283 case SDLK_UP:
284 return PUA_UP;
285 case SDLK_DOWN:
286 return PUA_DOWN;
287 case SDLK_LEFT:
288 return PUA_LEFT;
289 case SDLK_RIGHT:
290 return PUA_RIGHT;
291 default:
292 if (event.key.keysym.unicode != 0)
293 return event.key.keysym.unicode;
294 }
295 break;
296 case SDL_QUIT:
297 exit (0);
298 }
299 }
300 }
301
302
lock_screen(SDL_Surface * screen)303 void lock_screen (SDL_Surface *screen)
304 {
305 if (SDL_MUSTLOCK (screen))
306 if (SDL_LockSurface (screen) < 0)
307 fatal (2, "can't lock screen\n");
308 }
309
310
unlock_screen(SDL_Surface * screen)311 void unlock_screen (SDL_Surface *screen)
312 {
313 if (SDL_MUSTLOCK (screen))
314 SDL_UnlockSurface (screen);
315 }
316
317
fill_screen(SDL_Surface * screen,uint32_t color)318 void fill_screen (SDL_Surface *screen, uint32_t color)
319 {
320 SDL_Rect rect;
321 rect.x = 0;
322 rect.y = 0;
323 rect.w = screen->w;
324 rect.h = screen->h;
325 if (SDL_FillRect (screen, & rect, color) < 0)
326 fatal (2, "SDL_FillRect failed; %s\n", SDL_GetError ());
327 }
328
329
draw_horiz_lines(SDL_Surface * screen,uint32_t color,int pitch,int offset)330 void draw_horiz_lines (SDL_Surface *screen,
331 uint32_t color,
332 int pitch,
333 int offset)
334 {
335 SDL_Rect rect;
336 rect.x = 0;
337 rect.w = screen->w;
338 rect.h = 1;
339
340 for (rect.y = offset; rect.y < screen->h; rect.y += pitch)
341 if (SDL_FillRect (screen, & rect, color) < 0)
342 fatal (2, "SDL_FillRect failed; %s\n", SDL_GetError ());
343 }
344
345
draw_vert_lines(SDL_Surface * screen,uint32_t color,int pitch,int offset)346 void draw_vert_lines (SDL_Surface *screen,
347 uint32_t color,
348 int pitch,
349 int offset)
350 {
351 SDL_Rect rect;
352 rect.y = 0;
353 rect.h = screen->h;
354 rect.w = 1;
355
356 for (rect.x = offset; rect.x < screen->w; rect.x += pitch)
357 if (SDL_FillRect (screen, & rect, color) < 0)
358 fatal (2, "SDL_FillRect failed; %s\n", SDL_GetError ());
359 }
360
361
draw_diagonal_lines(SDL_Surface * screen,uint32_t color,int h_pitch,int h_offset,int v_pitch UNUSED,int v_offset,int slope)362 void draw_diagonal_lines (SDL_Surface *screen,
363 uint32_t color,
364 int h_pitch,
365 int h_offset,
366 int v_pitch UNUSED,
367 int v_offset,
368 int slope) // -1 or +1 if 45 degree angle
369 {
370 SDL_Rect rect;
371 rect.h = 1;
372 rect.w = 1;
373
374 h_offset -= (v_offset * slope);
375 if (h_offset < 0)
376 h_offset += h_pitch;
377 else if (h_offset >= h_pitch)
378 h_offset -= h_pitch;
379
380 for (rect.y = 0; rect.y < screen->h; rect.y++)
381 {
382 for (rect.x = h_offset % h_pitch; rect.x < screen->w; rect.x += h_pitch)
383 if (SDL_FillRect (screen, & rect, color) < 0)
384 fatal (2, "SDL_FillRect failed; %s\n", SDL_GetError ());
385 h_offset += slope;
386 if (h_offset < 0)
387 h_offset += h_pitch;
388 else if (h_offset >= h_pitch)
389 h_offset -= h_pitch;
390 }
391 }
392
393
draw_dots(SDL_Surface * screen,uint32_t color,int h_pitch,int h_offset,int v_pitch,int v_offset)394 void draw_dots (SDL_Surface *screen,
395 uint32_t color,
396 int h_pitch,
397 int h_offset,
398 int v_pitch,
399 int v_offset)
400 {
401 SDL_Rect rect;
402 rect.h = 1;
403 rect.w = 1;
404
405 for (rect.x = h_offset; rect.x < screen->w; rect.x += h_pitch)
406 for (rect.y = v_offset; rect.y < screen->h; rect.y += v_pitch)
407 if (SDL_FillRect (screen, & rect, color) < 0)
408 fatal (2, "SDL_FillRect failed; %s\n", SDL_GetError ());
409 }
410
411
412 uint32_t black;
413
414
pattern_solid(SDL_Surface * screen,uint32_t color)415 void pattern_solid (SDL_Surface *screen, uint32_t color)
416 {
417 lock_screen (screen);
418 fill_screen (screen, color);
419 unlock_screen (screen);
420 SDL_UpdateRect (screen, 0, 0, screen->w, screen->h);
421 }
422
pattern_horiz_lines(SDL_Surface * screen,uint32_t color,int v_pitch,int v_offset)423 void pattern_horiz_lines (SDL_Surface *screen,
424 uint32_t color,
425 int v_pitch,
426 int v_offset)
427 {
428 lock_screen (screen);
429 fill_screen (screen, black);
430 draw_horiz_lines (screen, color, v_pitch, v_offset);
431 unlock_screen (screen);
432 SDL_UpdateRect (screen, 0, 0, screen->w, screen->h);
433 }
434
pattern_vert_lines(SDL_Surface * screen,uint32_t color,int h_pitch,int h_offset)435 void pattern_vert_lines (SDL_Surface *screen,
436 uint32_t color,
437 int h_pitch,
438 int h_offset)
439 {
440 lock_screen (screen);
441 fill_screen (screen, black);
442 draw_vert_lines (screen, color, h_pitch, h_offset);
443 unlock_screen (screen);
444 SDL_UpdateRect (screen, 0, 0, screen->w, screen->h);
445 }
446
pattern_crosshatch(SDL_Surface * screen,uint32_t color,int h_pitch,int h_offset,int v_pitch,int v_offset)447 void pattern_crosshatch (SDL_Surface *screen,
448 uint32_t color,
449 int h_pitch,
450 int h_offset,
451 int v_pitch,
452 int v_offset)
453 {
454 lock_screen (screen);
455 fill_screen (screen, black);
456 draw_horiz_lines (screen, color, v_pitch, v_offset);
457 draw_vert_lines (screen, color, h_pitch, h_offset);
458 unlock_screen (screen);
459 SDL_UpdateRect (screen, 0, 0, screen->w, screen->h);
460 }
461
pattern_diagonal(SDL_Surface * screen,uint32_t color,int h_pitch,int h_offset,int v_pitch,int v_offset)462 void pattern_diagonal (SDL_Surface *screen,
463 uint32_t color,
464 int h_pitch,
465 int h_offset,
466 int v_pitch,
467 int v_offset)
468 {
469 lock_screen (screen);
470 fill_screen (screen, black);
471 draw_diagonal_lines (screen, color, h_pitch, h_offset, v_pitch, v_offset, -1);
472 draw_diagonal_lines (screen, color, h_pitch, h_offset, v_pitch, v_offset, +1);
473 unlock_screen (screen);
474 SDL_UpdateRect (screen, 0, 0, screen->w, screen->h);
475 }
476
pattern_dots(SDL_Surface * screen,uint32_t color,int h_pitch,int h_offset,int v_pitch,int v_offset)477 void pattern_dots (SDL_Surface *screen,
478 uint32_t color,
479 int h_pitch,
480 int h_offset,
481 int v_pitch,
482 int v_offset)
483 {
484 lock_screen (screen);
485 fill_screen (screen, black);
486 draw_dots (screen, color, h_pitch, h_offset, v_pitch, v_offset);
487 unlock_screen (screen);
488 SDL_UpdateRect (screen, 0, 0, screen->w, screen->h);
489 }
490
491
show_help(SDL_Surface * screen,SDL_Surface * help_image)492 void show_help (SDL_Surface *screen, SDL_Surface *help_image)
493 {
494 SDL_Rect src_rect, dest_rect;
495
496 src_rect.x = 0;
497 src_rect.h = help_image->h;
498 src_rect.y = 0;
499 src_rect.w = help_image->w;
500
501 dest_rect.x = (screen->w - help_image->w) / 2;
502 dest_rect.h = help_image->h;
503 dest_rect.y = (screen->h - help_image->h) / 2;
504 dest_rect.w = help_image->w;
505
506 lock_screen (screen);
507 SDL_BlitSurface (help_image, & src_rect, screen, & dest_rect);
508 unlock_screen (screen);
509 SDL_UpdateRect (screen, dest_rect.x, dest_rect.y, dest_rect.w, dest_rect.h);
510 }
511
512
513 typedef enum { solid, vert_lines, horiz_lines, crosshatch, dots, diagonal } pattern_t;
514
515
516 #define set_pitch(x) do \
517 if ((pattern != solid) && ((x) < screen->w) && ((x) < screen->h)) \
518 pitch = (x); \
519 while (0)
520
521
522 SDL_Surface *help_teaser_image;
523 SDL_Surface *help_image;
524
525
main_loop(SDL_Surface * screen)526 void main_loop (SDL_Surface *screen)
527 {
528 pattern_t pattern = crosshatch;
529 uint32_t fg_color;
530 int pitch = 32;
531 int h_offset = 0;
532 int v_offset = 0;
533 uint16_t key_unicode;
534 int help_flag = 1; // 0 for hidden, 1 for teaser, 2 for full help
535
536 black = SDL_MapRGB (screen->format, 0x00, 0x00, 0x00);
537
538 fg_color = SDL_MapRGB (screen->format, 0xff, 0x00, 0x00);
539
540 SDL_EnableKeyRepeat (SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
541
542 while (1)
543 {
544 if (h_offset >= pitch)
545 h_offset %= pitch;
546 if (v_offset >= pitch)
547 v_offset %= pitch;
548
549 switch (pattern)
550 {
551 case solid:
552 pattern_solid (screen, fg_color);
553 break;
554 case vert_lines:
555 pattern_vert_lines (screen, fg_color, pitch, h_offset);
556 break;
557 case horiz_lines:
558 pattern_horiz_lines (screen, fg_color, pitch, v_offset);
559 break;
560 case crosshatch:
561 pattern_crosshatch (screen, fg_color, pitch, h_offset, pitch, v_offset);
562 break;
563 case diagonal:
564 pattern_diagonal (screen, fg_color, pitch, h_offset, pitch, v_offset);
565 break;
566 case dots:
567 pattern_dots (screen, fg_color, pitch, h_offset, pitch, v_offset);
568 break;
569 }
570
571 if (help_flag == 1)
572 show_help (screen, help_teaser_image);
573 else if (help_flag == 2)
574 show_help (screen, help_image);
575
576 key_unicode = wait_key ();
577 switch (key_unicode)
578 {
579 case PUA_ESCAPE:
580 case L'q':
581 case L'Q':
582 exit (0);
583 case L'r':
584 case L'R':
585 fg_color = SDL_MapRGB (screen->format, 0xff, 0x00, 0x00);
586 help_flag = 0;
587 break;
588 case L'g':
589 case L'G':
590 fg_color = SDL_MapRGB (screen->format, 0x00, 0xff, 0x00);
591 help_flag = 0;
592 break;
593 case L'b':
594 case L'B':
595 fg_color = SDL_MapRGB (screen->format, 0x00, 0x00, 0xff);
596 help_flag = 0;
597 break;
598 case L'w':
599 case L'W':
600 fg_color = SDL_MapRGB (screen->format, 0xff, 0xff, 0xff);
601 help_flag = 0;
602 break;
603 case L'k':
604 case L'K':
605 fg_color = SDL_MapRGB (screen->format, 0x00, 0x00, 0x00);
606 help_flag = 0;
607 break;
608 case L'a':
609 case L'A':
610 fg_color = SDL_MapRGB (screen->format, 0xff, 0xff, 0xff);
611 pattern = vert_lines;
612 pitch = 2;
613 h_offset = 0;
614 help_flag = 0;
615 break;
616 case L's':
617 case L'S':
618 pattern = solid;
619 help_flag = 0;
620 break;
621 case L'v':
622 case L'V':
623 pattern = vert_lines;
624 help_flag = 0;
625 break;
626 case L'h':
627 case L'H':
628 pattern = horiz_lines;
629 help_flag = 0;
630 break;
631 case L'c':
632 case L'C':
633 pattern = crosshatch;
634 help_flag = 0;
635 break;
636 case L'x':
637 case L'X':
638 pattern = diagonal;
639 help_flag = 0;
640 break;
641 case L'd':
642 case L'D':
643 pattern = dots;
644 help_flag = 0;
645 break;
646 case PUA_UP:
647 v_offset = v_offset - 1;
648 if (v_offset < 0)
649 v_offset = pitch - 1;
650 help_flag = 0;
651 break;
652 case PUA_DOWN:
653 v_offset = v_offset + 1;
654 if (v_offset >= pitch)
655 v_offset = 0;
656 help_flag = 0;
657 break;
658 case PUA_LEFT:
659 h_offset = h_offset - 1;
660 if (h_offset < 0)
661 h_offset = pitch - 1;
662 help_flag = 0;
663 break;
664 case PUA_RIGHT:
665 h_offset = h_offset + 1;
666 if (h_offset >= pitch)
667 h_offset = 0;
668 help_flag = 0;
669 break;
670 case L'-':
671 if ((pattern != solid) && (pitch > 2))
672 pitch--;
673 help_flag = 0;
674 break;
675 case L'+':
676 case L'=':
677 set_pitch (pitch+1);
678 help_flag = 0;
679 break;
680 case L'0': set_pitch ( 4); help_flag = 0; break;
681 case L'1': set_pitch ( 8); help_flag = 0; break;
682 case L'2': set_pitch ( 16); help_flag = 0; break;
683 case L'3': set_pitch ( 32); help_flag = 0; break;
684 case L'4': set_pitch ( 64); help_flag = 0; break;
685 case L'5': set_pitch ( 96); help_flag = 0; break;
686 case L'6': set_pitch (128); help_flag = 0; break;
687 case L'7': set_pitch (192); help_flag = 0; break;
688 case L'8': set_pitch (256); help_flag = 0; break;
689 case L'9': set_pitch (320); help_flag = 0; break;
690 case L'/':
691 case L'?':
692 if (help_flag == 2)
693 help_flag = 0;
694 else
695 help_flag = 2;
696 break;
697 default:
698 break;
699 }
700 }
701 }
702
703
enumerate_sdl_modes(int * width,int * height,FILE * out)704 int enumerate_sdl_modes (int *width, int *height, FILE *out)
705 {
706 SDL_Rect **modes;
707 int w = -1;
708 int h = -1;
709 int m = -1;
710 int i;
711
712 modes = SDL_ListModes (NULL, SDL_HWSURFACE | SDL_FULLSCREEN);
713
714 if (! modes)
715 fatal (2, "no SDL display modes available\n");
716
717 if (modes == (SDL_Rect **) -1)
718 fatal (2, "all SDL resolutions available (on hardware?)\n");
719
720 for (i = 0; modes [i]; i++)
721 {
722 if (((*width) >= 0) & (modes [i]->w != *width))
723 continue;
724 if (((*height) >= 0) & (modes [i]->h != *height))
725 continue;
726 if (out)
727 fprintf (out, " mode %d: %d x %d\n", i, modes [i]->w, modes [i]->h);
728 if ((modes [i]->w >= w) && (modes [i]->h >= h))
729 {
730 w = modes [i]->w;
731 h = modes [i]->h;
732 m = i;
733 }
734 }
735
736 if (m < 0)
737 fatal (2, "no matching SDL video modes found\n");
738
739 *width = w;
740 *height = h;
741 return (m);
742 }
743
744
745 const char font_path [] = "/usr/local/share/fonts/Liberation/LiberationMono-Regular.ttf";
746
main(int argc,char * argv[])747 int main (int argc, char *argv [])
748 {
749 SDL_Surface *screen;
750 bool fullscreen = true;
751 uint32_t sdl_flags;
752 int width = -1;
753 int height = -1;
754 SDL_Color black = { 0x00, 0x00, 0x00, 0x00 };
755 SDL_Color white = { 0xff, 0xff, 0xff, 0x00 };
756
757 progname = argv [0];
758
759 if (SDL_Init (SDL_INIT_VIDEO) < 0)
760 fatal (2, "SDL initialization error %s\n", SDL_GetError ());
761 atexit (SDL_Quit);
762 SDL_EnableUNICODE (1);
763
764 help_teaser_image = create_text_surface (help_teaser_message,
765 font_path,
766 18,
767 white,
768 black);
769 help_image = create_text_surface (help_message,
770 font_path,
771 18,
772 white,
773 black);
774
775 while (--argc)
776 {
777 argv++;
778 if ((strcmp (argv [0], "--help") == 0) ||
779 (strcmp (argv [0], "-?") == 0))
780 {
781 usage (stderr);
782 help (stderr);
783 exit (0);
784 }
785 else if (strcmp (argv [0], "--list-modes") == 0)
786 {
787 fprintf (stderr, "SDL video modes:\n");
788 enumerate_sdl_modes (& width, & height, stderr);
789 exit (0);
790 }
791 else if ((strcmp (argv [0], "--window") == 0) ||
792 (strcmp (argv [0], "-w") == 0))
793 {
794 fullscreen = false;
795 if (width < 0)
796 width = 620;
797 if (height < 0)
798 height = 460;
799 }
800 else if (strcmp (argv [0], "-x") == 0)
801 {
802 if (--argc == 0)
803 fatal (1, "-x option must be followed by resolution\n");
804 width = atoi (argv [1]);
805 argv++;
806 }
807 else if (strcmp (argv [0], "-y") == 0)
808 {
809 if (--argc == 0)
810 fatal (1, "-y option must be followed by resolution\n");
811 height = atoi (argv [1]);
812 argv++;
813 }
814 else
815 fatal (1, "unrecognized option '%s'\n", argv [0]);
816 }
817
818 if (fullscreen)
819 {
820 enumerate_sdl_modes (& width, & height, NULL);
821 //printf ("using video resolution %d x %d\n", width, height);
822 sdl_flags = SDL_HWSURFACE | SDL_FULLSCREEN;
823 }
824 else
825 sdl_flags = SDL_SWSURFACE;
826
827 screen = SDL_SetVideoMode (width, height, 32, sdl_flags);
828 if (! screen)
829 fatal (2, "can't set video mode: %s\n", SDL_GetError ());
830
831 if (fullscreen)
832 SDL_ShowCursor (SDL_DISABLE);
833
834 main_loop (screen);
835
836 exit (0);
837 }
838