1 /*         ______   ___    ___
2  *        /\  _  \ /\_ \  /\_ \
3  *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___
4  *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
5  *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
6  *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7  *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8  *                                           /\____/
9  *                                           \_/__/
10  *
11  *      Allegro library utility for checking which VBE/AF modes are available.
12  *
13  *      By Shawn Hargreaves.
14  *
15  *      See readme.txt for copyright information.
16  */
17 
18 #define ALLEGRO_USE_CONSOLE
19 
20 #include <stdio.h>
21 #include <string.h>
22 
23 #include "allegro.h"
24 
25 
26 /* this program is not portable! */
27 #if (defined ALLEGRO_DOS) || (defined ALLEGRO_LINUX_VBEAF)
28 
29 #include "allegro/internal/aintern.h"
30 
31 #ifdef ALLEGRO_INTERNAL_HEADER
32    #include ALLEGRO_INTERNAL_HEADER
33 #endif
34 
35 #if (defined ALLEGRO_DJGPP) && (!defined SCAN_DEPEND)
36    #include <sys/nearptr.h>
37 #endif
38 
39 
40 
41 #ifdef ALLEGRO_LINUX
42 
43    #include <sys/mman.h>
44 
45    /* quick and dirty Linux emulation of the DOS memory mapping routines */
46    #define _create_linear_mapping(_addr, _base, _len)       \
47    ({                                                       \
48       (_addr)->base = _base;                                \
49       (_addr)->size = _len;                                 \
50       (_addr)->perms = PROT_READ | PROT_WRITE;              \
51       __al_linux_map_memory(_addr);                         \
52    })
53 
54    #define _remove_linear_mapping(_addr)                    \
55    {                                                        \
56       if ((_addr)->data)                                    \
57 	 __al_linux_unmap_memory(_addr);                    \
58    }
59 
60    #define MMAP      struct MAPPED_MEMORY
61    #define NOMM      { 0, 0, 0, 0 }
62    #define MVAL(a)   a.data
63 
64 #else
65 
66    /* DOS version */
67    #define MMAP      unsigned long
68    #define NOMM      0
69    #define MVAL(a)   (void *)((a)-__djgpp_base_address)
70 
71 #endif
72 
73 
74 
75 int verbose = FALSE;
76 
77 
78 
79 #ifdef ALLEGRO_GCC
80    #define __PACKED__   __attribute__ ((packed))
81 #else
82    #define __PACKED__
83 #endif
84 
85 #ifdef ALLEGRO_WATCOM
86    #pragma pack (1)
87 #endif
88 
89 
90 
91 typedef struct AF_MODE_INFO
92 {
93    unsigned short Attributes              __PACKED__;
94    unsigned short XResolution             __PACKED__;
95    unsigned short YResolution             __PACKED__;
96    unsigned short BytesPerScanLine        __PACKED__;
97    unsigned short BitsPerPixel            __PACKED__;
98    unsigned short MaxBuffers              __PACKED__;
99    unsigned char  RedMaskSize;
100    unsigned char  RedFieldPosition;
101    unsigned char  GreenMaskSize;
102    unsigned char  GreenFieldPosition;
103    unsigned char  BlueMaskSize;
104    unsigned char  BlueFieldPosition;
105    unsigned char  RsvdMaskSize;
106    unsigned char  RsvdFieldPosition;
107    unsigned short MaxBytesPerScanLine     __PACKED__;
108    unsigned short MaxScanLineWidth        __PACKED__;
109    unsigned short LinBytesPerScanLine     __PACKED__;
110    unsigned char  BnkMaxBuffers;
111    unsigned char  LinMaxBuffers;
112    unsigned char  LinRedMaskSize;
113    unsigned char  LinRedFieldPosition;
114    unsigned char  LinGreenMaskSize;
115    unsigned char  LinGreenFieldPosition;
116    unsigned char  LinBlueMaskSize;
117    unsigned char  LinBlueFieldPosition;
118    unsigned char  LinRsvdMaskSize;
119    unsigned char  LinRsvdFieldPosition;
120    unsigned long  MaxPixelClock           __PACKED__;
121    unsigned long  VideoCapabilities       __PACKED__;
122    unsigned short VideoMinXScale          __PACKED__;
123    unsigned short VideoMinYScale          __PACKED__;
124    unsigned short VideoMaxXScale          __PACKED__;
125    unsigned short VideoMaxYScale          __PACKED__;
126    unsigned char  reserved[76];
127 } AF_MODE_INFO;
128 
129 
130 
131 #define DC  struct AF_DRIVER *dc
132 
133 
134 
135 typedef struct AF_DRIVER
136 {
137    char           Signature[12];
138    unsigned long  Version                 __PACKED__;
139    unsigned long  DriverRev               __PACKED__;
140    char           OemVendorName[80];
141    char           OemCopyright[80];
142    short          *AvailableModes         __PACKED__;
143    unsigned long  TotalMemory             __PACKED__;
144    unsigned long  Attributes              __PACKED__;
145    unsigned long  BankSize                __PACKED__;
146    unsigned long  BankedBasePtr           __PACKED__;
147    unsigned long  LinearSize              __PACKED__;
148    unsigned long  LinearBasePtr           __PACKED__;
149    unsigned long  LinearGranularity       __PACKED__;
150    unsigned short *IOPortsTable           __PACKED__;
151    unsigned long  IOMemoryBase[4]         __PACKED__;
152    unsigned long  IOMemoryLen[4]          __PACKED__;
153    unsigned long  LinearStridePad         __PACKED__;
154    unsigned short PCIVendorID             __PACKED__;
155    unsigned short PCIDeviceID             __PACKED__;
156    unsigned short PCISubSysVendorID       __PACKED__;
157    unsigned short PCISubSysID             __PACKED__;
158    unsigned long  Checksum                __PACKED__;
159    unsigned long  res2[6]                 __PACKED__;
160    void           *IOMemMaps[4]           __PACKED__;
161    void           *BankedMem              __PACKED__;
162    void           *LinearMem              __PACKED__;
163    unsigned long  res3[5]                 __PACKED__;
164    unsigned long  BufferEndX              __PACKED__;
165    unsigned long  BufferEndY              __PACKED__;
166    unsigned long  OriginOffset            __PACKED__;
167    unsigned long  OffscreenOffset         __PACKED__;
168    unsigned long  OffscreenStartY         __PACKED__;
169    unsigned long  OffscreenEndY           __PACKED__;
170    unsigned long  res4[10]                __PACKED__;
171    unsigned long  SetBank32Len            __PACKED__;
172    void           *SetBank32;
173    void           *Int86;
174    void           *CallRealMode;
175    void           *InitDriver;
176    void           *af10Funcs[40];
177    void           *PlugAndPlayInit;
178    void           *(*OemExt)(DC, unsigned long id);
179    void           *SupplementalExt;
180    long           (*GetVideoModeInfo)(DC, short mode, AF_MODE_INFO *modeInfo);
181 } AF_DRIVER;
182 
183 
184 
185 #undef DC
186 
187 
188 
189 #define FAF_ID(a,b,c,d)    ((a<<24) | (b<<16) | (c<<8) | d)
190 
191 #define FAFEXT_INIT     FAF_ID('I','N','I','T')
192 #define FAFEXT_MAGIC    FAF_ID('E','X', 0,  0)
193 
194 #define FAFEXT_LIBC     FAF_ID('L','I','B','C')
195 #define FAFEXT_PMODE    FAF_ID('P','M','O','D')
196 
197 #define FAFEXT_HWPTR    FAF_ID('H','P','T','R')
198 
199 #define FAFEXT_CONFIG   FAF_ID('C','O','N','F')
200 
201 
202 typedef struct FAF_CONFIG_DATA
203 {
204    unsigned long id;
205    unsigned long value;
206 } FAF_CONFIG_DATA;
207 
208 
209 
210 AF_DRIVER *af = NULL;
211 
212 MMAP af_memmap[4] = { NOMM, NOMM, NOMM, NOMM };
213 MMAP af_banked_mem = NOMM;
214 MMAP af_linear_mem = NOMM;
215 
216 
217 
218 #ifdef ALLEGRO_DOS
219 
220 /* hooks to let the driver call BIOS routines */
221 extern void _af_int86(void), _af_call_rm(void);
222 
223 #else
224 
225 /* no BIOS on this platform, my friend! */
nobios(void)226 void nobios(void) { }
227 
228 #endif
229 
230 
231 
af_exit(void)232 void af_exit(void)
233 {
234    int c;
235 
236    for (c=0; c<4; c++)
237       _remove_linear_mapping(&af_memmap[c]);
238 
239    _remove_linear_mapping(&af_banked_mem);
240    _remove_linear_mapping(&af_linear_mem);
241 
242    if (af) {
243       free(af);
244       af = NULL;
245    }
246 }
247 
248 
249 
call_vbeaf_asm(void * proc)250 static int call_vbeaf_asm(void *proc)
251 {
252    int ret;
253 
254    proc = (void *)((long)af + (long)proc);
255 
256    #ifdef ALLEGRO_GCC
257 
258       /* use gcc-style inline asm */
259       asm (
260 	 " call *%%edx "
261 
262       : "=&a" (ret)                       /* return value in eax */
263 
264       : "b" (af),                         /* VBE/AF driver in ds:ebx */
265 	"d" (proc)                        /* function ptr in edx */
266 
267       : "memory"                          /* assume everything is clobbered */
268       );
269 
270    #elif defined ALLEGRO_WATCOM
271 
272       /* use Watcom-style inline asm */
273       {
274 	 int _af(void *func, AF_DRIVER *driver);
275 
276 	 #pragma aux _af =                \
277 	    " call esi "                  \
278 					  \
279 	 parm [esi] [ebx]                 \
280 	 modify [ecx edx edi]             \
281 	 value [eax];
282 
283 	 ret = _af(proc, af);
284       }
285 
286    #else
287 
288       /* don't know what to do on this compiler */
289       ret = -1;
290 
291    #endif
292 
293    return ret;
294 }
295 
296 
297 
load_vbeaf_driver(char * filename)298 int load_vbeaf_driver(char *filename)
299 {
300    long size;
301    PACKFILE *f;
302 
303    size = file_size_ex(filename);
304    if (size <= 0)
305       return -1;
306 
307    f = pack_fopen(filename, F_READ);
308    if (!f)
309       return -1;
310 
311    af = malloc(size);
312 
313    if (pack_fread(af, size, f) != size) {
314       free(af);
315       af = NULL;
316       return -1;
317    }
318 
319    pack_fclose(f);
320 
321    return 0;
322 }
323 
324 
325 
initialise_freebeaf_extensions(void)326 void initialise_freebeaf_extensions(void)
327 {
328    typedef unsigned long (*EXT_INIT_FUNC)(AF_DRIVER *af, unsigned long id);
329    EXT_INIT_FUNC ext_init;
330    FAF_CONFIG_DATA *cfg;
331    unsigned long magic;
332    int v1, v2;
333 
334    if (!af->OemExt) {
335       printf("no OemExt\n");
336       return;
337    }
338 
339    ext_init = (EXT_INIT_FUNC)((long)af + (long)af->OemExt);
340 
341    magic = ext_init(af, FAFEXT_INIT);
342 
343    v1 = (magic>>8)&0xFF;
344    v2 = magic&0xFF;
345 
346    if (((magic&0xFFFF0000) != FAFEXT_MAGIC) || (!uisdigit(v1)) || (!uisdigit(v2))) {
347       printf("bad magic number!\n");
348       return;
349    }
350 
351    printf("EX%c%c", v1, v2);
352 
353    if (af->OemExt(af, FAFEXT_LIBC))
354       printf(", FAFEXT_LIBC");
355 
356    if (af->OemExt(af, FAFEXT_PMODE))
357       printf(", FAFEXT_PMODE");
358 
359    if (af->OemExt(af, FAFEXT_HWPTR))
360       printf(", FAFEXT_HWPTR");
361 
362    cfg = af->OemExt(af, FAFEXT_CONFIG);
363    if (cfg)
364       printf(", FAFEXT_CONFIG");
365 
366    printf("\n");
367 
368    if (cfg) {
369       while (cfg->id) {
370 	 printf("Config variable:\t%c%c%c%c = 0x%08lX\n",
371 		(char)(cfg->id>>24), (char)(cfg->id>>16),
372 		(char)(cfg->id>>8), (char)(cfg->id), cfg->value);
373 
374 	 cfg++;
375       }
376    }
377 }
378 
379 
380 
initialise_vbeaf(void)381 static int initialise_vbeaf(void)
382 {
383    int c;
384 
385    #ifdef ALLEGRO_DOS
386       if (__djgpp_nearptr_enable() == 0)
387 	 return -1;
388    #else
389       if (!__al_linux_have_ioperms)
390 	 return -1;
391    #endif
392 
393    for (c=0; c<4; c++) {
394       if (af->IOMemoryBase[c]) {
395 	 if (_create_linear_mapping(&af_memmap[c], af->IOMemoryBase[c],
396 				    af->IOMemoryLen[c]) != 0)
397 	    return -1;
398 
399 	 af->IOMemMaps[c] = MVAL(af_memmap[c]);
400       }
401    }
402 
403    if (af->BankedBasePtr) {
404       if (_create_linear_mapping(&af_banked_mem, af->BankedBasePtr, 0x10000) != 0)
405 	 return -1;
406 
407       af->BankedMem = MVAL(af_banked_mem);
408    }
409 
410    if (af->LinearBasePtr) {
411       if (_create_linear_mapping(&af_linear_mem, af->LinearBasePtr, af->LinearSize*1024) != 0)
412 	 return -1;
413 
414       af->LinearMem  = MVAL(af_linear_mem);
415    }
416 
417    #ifdef ALLEGRO_DOS
418       af->Int86 = _af_int86;
419       af->CallRealMode = _af_call_rm;
420    #else
421       af->Int86 = nobios;
422       af->CallRealMode = nobios;
423    #endif
424 
425    return 0;
426 }
427 
428 
429 
print_af_attributes(unsigned long attrib)430 void print_af_attributes(unsigned long attrib)
431 {
432    static char *flags[] =
433    {
434       "multibuf",
435       "scroll",
436       "banked",
437       "linear",
438       "accel",
439       "dualbuf",
440       "hwcursor",
441       "8bitdac",
442       "nonvga",
443       "2scan",
444       "interlace",
445       "3buffer",
446       "stereo",
447       "rop2",
448       "hwstsync",
449       "evcstsync"
450    };
451 
452    int first = TRUE;
453    int c;
454 
455    printf("Attributes:\t\t");
456 
457    for (c=0; c<(int)(sizeof(flags)/sizeof(flags[0])); c++) {
458       if (attrib & (1<<c)) {
459 	 if (first)
460 	    first = FALSE;
461 	 else
462 	    printf(", ");
463 
464 	 printf(flags[c]);
465       }
466    }
467 
468    printf("\n");
469 }
470 
471 
472 
get_af_info(void)473 int get_af_info(void)
474 {
475    static char *possible_filenames[] =
476    {
477    #ifdef ALLEGRO_DOS
478       "c:\\vbeaf.drv",
479    #else
480       "/usr/local/lib/vbeaf.drv",
481       "/usr/lib/vbeaf.drv",
482       "/lib/vbeaf.drv",
483       "/vbeaf.drv",
484    #endif
485       NULL
486    };
487 
488    char filename[256];
489    AL_CONST char *p;
490    int c, attrib;
491 
492    p = get_config_string(NULL, "vbeaf_driver", NULL);
493    if ((p) && (*p)) {
494       strcpy(filename, p);
495       if (*get_filename(filename) == 0) {
496 	 strcat(filename, "vbeaf.drv");
497       }
498       else {
499 	 if (file_exists(filename, FA_DIREC, &attrib)) {
500 	    if (attrib & FA_DIREC) {
501 	       put_backslash(filename);
502 	       strcat(filename, "vbeaf.drv");
503 	    }
504 	 }
505       }
506       if (load_vbeaf_driver(filename) == 0)
507 	 goto found_it;
508    }
509 
510    for (c=0; possible_filenames[c]; c++) {
511       strcpy(filename, possible_filenames[c]);
512       if (load_vbeaf_driver(filename) == 0)
513 	 goto found_it;
514    }
515 
516    p = getenv("VBEAF_PATH");
517    if (p) {
518       strcpy(filename, p);
519       put_backslash(filename);
520       strcat(filename, "vbeaf.drv");
521       if (load_vbeaf_driver(filename) == 0)
522 	 goto found_it;
523    }
524 
525    #ifdef ALLEGRO_DOS
526       printf("Error: no VBE/AF driver found!\nYou should have a vbeaf.drv file in the root of your C: drive\n");
527    #else
528       printf("Error: no VBE/AF driver found!\nYou should have a vbeaf.drv file in the root of your filesystem\n");
529    #endif
530 
531    return -1;
532 
533    found_it:
534 
535    printf("Driver file:\t\t%s\n", filename);
536 
537    if (strcmp(af->Signature, "VBEAF.DRV") != 0) {
538       af_exit();
539       printf("\nError: bad header ID in this driver file!\n");
540       return -1;
541    }
542 
543    if (af->Version < 0x200) {
544       af_exit();
545       printf("Error: obsolete driver version! (0x%lX)\n", af->Version);
546       return -1;
547    }
548 
549    printf("FreeBE/AF ext:\t\t");
550 
551    if (strstr(af->OemVendorName, "FreeBE"))
552       initialise_freebeaf_extensions();
553    else
554       printf("not a FreeBE/AF driver\n");
555 
556    if (call_vbeaf_asm(af->PlugAndPlayInit) != 0) {
557       af_exit();
558       printf("\nError: VBE/AF Plug and Play initialisation failed!\n");
559       return -1;
560    }
561 
562    if (initialise_vbeaf() != 0) {
563       af_exit();
564       printf("\nError: cannot map VBE/AF device memory!\n");
565       return -1;
566    }
567 
568    if (call_vbeaf_asm(af->InitDriver) != 0) {
569       af_exit();
570       printf("\nError: VBE/AF device not present!\n");
571       return -1;
572    }
573 
574    printf("VBE/AF version:\t\t0x%lX\n", af->Version);
575    printf("VendorName:\t\t%s\n", af->OemVendorName);
576    printf("VendorCopyright:\t%s\n", af->OemCopyright);
577    printf("TotalMemory:\t\t%ld\n", af->TotalMemory);
578 
579    print_af_attributes(af->Attributes);
580 
581    if (verbose) {
582       printf("BankedAddr:\t\t0x%08lX\n", af->BankedBasePtr);
583       printf("BankedSize:\t\t0x%08lX\n", af->BankSize*1024);
584       printf("LinearAddr:\t\t0x%08lX\n", af->LinearBasePtr);
585       printf("LinearSize:\t\t0x%08lX\n", af->LinearSize*1024);
586 
587       for (c=0; c<4; c++) {
588 	 printf("IOMemoryBase[%d]:\t0x%08lX\n", c, af->IOMemoryBase[c]);
589 	 printf("IOMemoryLen[%d]:\t\t0x%08lX\n", c, af->IOMemoryLen[c]);
590       }
591 
592       printf("\n\n\n");
593    }
594    else
595       printf("\n");
596 
597    return 0;
598 }
599 
600 
601 
602 typedef struct COLORINFO
603 {
604    int size;
605    int pos;
606    char c;
607 } COLORINFO;
608 
609 COLORINFO colorinfo[4];
610 
611 int colorcount = 0;
612 
613 
614 
color_cmp(const void * e1,const void * e2)615 int color_cmp(const void *e1, const void *e2)
616 {
617    COLORINFO *c1 = (COLORINFO *)e1;
618    COLORINFO *c2 = (COLORINFO *)e2;
619 
620    return c2->pos - c1->pos;
621 }
622 
623 
624 
add_color(int size,int pos,char c)625 void add_color(int size, int pos, char c)
626 {
627    if ((size > 0) || (pos > 0)) {
628       colorinfo[colorcount].size = size;
629       colorinfo[colorcount].pos = pos;
630       colorinfo[colorcount].c = c;
631       colorcount++;
632    }
633 }
634 
635 
636 
get_color_desc(char * s)637 void get_color_desc(char *s)
638 {
639    int c;
640 
641    if (colorcount > 0) {
642       qsort(colorinfo, colorcount, sizeof(COLORINFO), color_cmp);
643 
644       for (c=0; c<colorcount; c++)
645 	 *(s++) = colorinfo[c].c;
646 
647       *(s++) = ' ';
648 
649       for (c=0; c<colorcount; c++)
650 	 *(s++) = '0' + colorinfo[c].size;
651 
652       colorcount = 0;
653    }
654 
655    *s = 0;
656 }
657 
658 
659 
get_mode_info(int mode)660 int get_mode_info(int mode)
661 {
662    AF_MODE_INFO mode_info;
663    char color_desc[80];
664    char buf[80];
665 
666    if (!verbose) {
667       sprintf(buf, "%X:", mode);
668       printf("Mode 0x%-5s", buf);
669    }
670    else
671       printf("Mode 0x%X:\n\n", mode);
672 
673    if (af->GetVideoModeInfo(af, mode, &mode_info) != 0) {
674       printf("GetVideoModeInfo failed!\n");
675       if (verbose)
676 	 printf("\n\n\n");
677       return -1;
678    }
679 
680    add_color(mode_info.RedMaskSize, mode_info.RedFieldPosition, 'R');
681    add_color(mode_info.GreenMaskSize, mode_info.GreenFieldPosition, 'G');
682    add_color(mode_info.BlueMaskSize, mode_info.BlueFieldPosition, 'B');
683    add_color(mode_info.RsvdMaskSize, mode_info.RsvdFieldPosition, 'x');
684    get_color_desc(color_desc);
685 
686    if (verbose) {
687       print_af_attributes(mode_info.Attributes);
688 
689       if (color_desc[0])
690 	 printf("Format:\t\t\t%s\n", color_desc);
691 
692       printf("XResolution:\t\t%d\n", mode_info.XResolution);
693       printf("YResolution:\t\t%d\n", mode_info.YResolution);
694       printf("BitsPerPixel:\t\t%d\n", mode_info.BitsPerPixel);
695       printf("BytesPerScanLine:\t%d\n", mode_info.BytesPerScanLine);
696       printf("LinBytesPerScanLine:\t%d\n", mode_info.LinBytesPerScanLine);
697       printf("MaxBytesPerScanLine:\t%d\n", mode_info.MaxBytesPerScanLine);
698       printf("MaxScanLineWidth:\t%d\n", mode_info.MaxScanLineWidth);
699       printf("MaxBuffers:\t\t%d\n", mode_info.MaxBuffers);
700       printf("BnkMaxBuffers:\t\t%d\n", mode_info.BnkMaxBuffers);
701       printf("LinMaxBuffers:\t\t%d\n", mode_info.LinMaxBuffers);
702       printf("RedMaskSize:\t\t%d\n", mode_info.RedMaskSize);
703       printf("RedFieldPos:\t\t%d\n", mode_info.RedFieldPosition);
704       printf("GreenMaskSize:\t\t%d\n", mode_info.GreenMaskSize);
705       printf("GreenFieldPos:\t\t%d\n", mode_info.GreenFieldPosition);
706       printf("BlueMaskSize:\t\t%d\n", mode_info.BlueMaskSize);
707       printf("BlueFieldPos:\t\t%d\n", mode_info.BlueFieldPosition);
708       printf("RsvdMaskSize:\t\t%d\n", mode_info.RsvdMaskSize);
709       printf("RsvdFieldPos:\t\t%d\n", mode_info.RsvdFieldPosition);
710       printf("LinRedMaskSize:\t\t%d\n", mode_info.LinRedMaskSize);
711       printf("LinRedFieldPos:\t\t%d\n", mode_info.LinRedFieldPosition);
712       printf("LinGreenMaskSize:\t%d\n", mode_info.LinGreenMaskSize);
713       printf("LinGreenFieldPos:\t%d\n", mode_info.LinGreenFieldPosition);
714       printf("LinBlueMaskSize:\t%d\n", mode_info.LinBlueMaskSize);
715       printf("LinBlueFieldPos:\t%d\n", mode_info.LinBlueFieldPosition);
716       printf("LinRsvdMaskSize:\t%d\n", mode_info.LinRsvdMaskSize);
717       printf("LinRsvdFieldPos:\t%d\n", mode_info.LinRsvdFieldPosition);
718       printf("MaxPixelClock:\t\t%ld\n", mode_info.MaxPixelClock);
719 
720       printf("\n\n\n");
721    }
722    else {
723       printf("%5dx%-6d", mode_info.XResolution, mode_info.YResolution);
724       printf("%d bpp", mode_info.BitsPerPixel);
725       if (color_desc[0])
726 	 printf(" (%s)", color_desc);
727       printf("\n");
728    }
729 
730    return 0;
731 }
732 
733 
734 
main(int argc,char * argv[])735 int main(int argc, char *argv[])
736 {
737    int c;
738 
739    if (allegro_init() != 0)
740       return 1;
741 
742    #ifdef SYSTEM_XWINDOWS
743       if (system_driver->id == SYSTEM_XWINDOWS) {
744 	 allegro_message("Sorry, VBE/AF is not available under X, run AFINFO from Linux console\n");
745 	 return 1;
746       }
747    #endif
748 
749    #ifdef ALLEGRO_LINUX
750       if (!__al_linux_have_ioperms) {
751 	 printf("Sorry, you need to be root before you can do stuff with VBE/AF\n");
752 	 return 1;
753       }
754    #endif
755 
756    for (c=1; c<argc; c++)
757       if (((argv[c][0] == '-') || (argv[c][0] == '/')) &&
758 	  ((argv[c][1] == 'v') || (argv[c][1] == 'V')))
759 	 verbose = TRUE;
760 
761    printf("\nAllegro VBE/AF info utility " ALLEGRO_VERSION_STR ", " ALLEGRO_PLATFORM_STR);
762    printf("\nBy Shawn Hargreaves, " ALLEGRO_DATE_STR "\n\n");
763 
764    if (get_af_info() != 0)
765       return -1;
766 
767    for (c=0; af->AvailableModes[c] != -1; c++)
768       get_mode_info(af->AvailableModes[c]);
769 
770    if (!verbose)
771       printf("\n'afinfo -v' for a verbose listing\n\n");
772 
773    af_exit();
774 
775    return 0;
776 }
777 
778 
779 
780 #else       /* ifdef VBE/AF cool on this platform */
781 
782 
main(void)783 int main(void)
784 {
785    allegro_init();
786    allegro_message("Sorry, the AFINFO program only works on DOS or Linux\n");
787    return 1;
788 }
789 
790 
791 #endif
792 
793 
794 END_OF_MAIN()
795