1 /*         ______   ___    ___
2  *        /\  _  \ /\_ \  /\_ \
3  *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___
4  *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
5  *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
6  *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7  *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8  *                                           /\____/
9  *                                           \_/__/
10  *
11  *      Allegro library utility for checking which VESA 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 #ifdef ALLEGRO_DOS
28 
29 
30 
31 int verbose = FALSE;
32 
33 
34 #define MASK_LINEAR(addr)     (addr & 0x000FFFFF)
35 #define RM_TO_LINEAR(addr)    (((addr & 0xFFFF0000) >> 12) + (addr & 0xFFFF))
36 #define RM_OFFSET(addr)       (addr & 0xF)
37 #define RM_SEGMENT(addr)      ((addr >> 4) & 0xFFFF)
38 
39 
40 
41 #ifdef ALLEGRO_GCC
42    #define __PACKED__   __attribute__ ((packed))
43 #else
44    #define __PACKED__
45 #endif
46 
47 #ifdef ALLEGRO_WATCOM
48    #pragma pack (1)
49 #endif
50 
51 
52 
53 typedef struct VESA_INFO
54 {
55    char           VESASignature[4];
56    unsigned short VESAVersion          __PACKED__;
57    unsigned long  OEMStringPtr         __PACKED__;
58    unsigned char  Capabilities[4];
59    unsigned long  VideoModePtr         __PACKED__;
60    unsigned short TotalMemory          __PACKED__;
61    unsigned short OemSoftwareRev       __PACKED__;
62    unsigned long  OemVendorNamePtr     __PACKED__;
63    unsigned long  OemProductNamePtr    __PACKED__;
64    unsigned long  OemProductRevPtr     __PACKED__;
65    unsigned char  Reserved[222];
66    unsigned char  OemData[256];
67 } VESA_INFO;
68 
69 
70 
71 typedef struct MODE_INFO
72 {
73    unsigned short ModeAttributes       __PACKED__;
74    unsigned char  WinAAttributes;
75    unsigned char  WinBAttributes;
76    unsigned short WinGranularity       __PACKED__;
77    unsigned short WinSize              __PACKED__;
78    unsigned short WinASegment          __PACKED__;
79    unsigned short WinBSegment          __PACKED__;
80    unsigned long  WinFuncPtr           __PACKED__;
81    unsigned short BytesPerScanLine     __PACKED__;
82    unsigned short XResolution          __PACKED__;
83    unsigned short YResolution          __PACKED__;
84    unsigned char  XCharSize;
85    unsigned char  YCharSize;
86    unsigned char  NumberOfPlanes;
87    unsigned char  BitsPerPixel;
88    unsigned char  NumberOfBanks;
89    unsigned char  MemoryModel;
90    unsigned char  BankSize;
91    unsigned char  NumberOfImagePages;
92    unsigned char  Reserved_page;
93    unsigned char  RedMaskSize;
94    unsigned char  RedMaskPos;
95    unsigned char  GreenMaskSize;
96    unsigned char  GreenMaskPos;
97    unsigned char  BlueMaskSize;
98    unsigned char  BlueMaskPos;
99    unsigned char  ReservedMaskSize;
100    unsigned char  ReservedMaskPos;
101    unsigned char  DirectColorModeInfo;
102    unsigned long  PhysBasePtr          __PACKED__;
103    unsigned long  OffScreenMemOffset   __PACKED__;
104    unsigned short OffScreenMemSize     __PACKED__;
105    unsigned short LinBytesPerScanLine  __PACKED__;
106    unsigned char  BnkNumberOfPages;
107    unsigned char  LinNumberOfPages;
108    unsigned char  LinRedMaskSize;
109    unsigned char  LinRedFieldPos;
110    unsigned char  LinGreenMaskSize;
111    unsigned char  LinGreenFieldPos;
112    unsigned char  LinBlueMaskSize;
113    unsigned char  LinBlueFieldPos;
114    unsigned char  LinRsvdMaskSize;
115    unsigned char  LinRsvdFieldPos;
116    unsigned long  MaxPixelClock        __PACKED__;
117    unsigned char  Reserved[190];
118 } MODE_INFO;
119 
120 
121 
122 VESA_INFO vesa_info;
123 MODE_INFO mode_info;
124 
125 
126 #define MAX_VESA_MODES 1024
127 
128 unsigned short mode[MAX_VESA_MODES];
129 int modes;
130 
131 
132 char oem_string[256];
133 char oemvendor_string[256];
134 char oemproductname_string[256];
135 char oemproductrev_string[256];
136 
137 
138 
get_string(char * s,unsigned long addr)139 void get_string(char *s, unsigned long addr)
140 {
141    if (addr) {
142       addr = RM_TO_LINEAR(addr);
143       while (_farnspeekb(addr) != 0)
144 	 *(s++) = _farnspeekb(addr++);
145       *s = 0;
146    }
147    else
148       strcpy(s, "(null)");
149 }
150 
151 
152 
get_vesa_info(void)153 int get_vesa_info(void)
154 {
155    __dpmi_regs r;
156    unsigned long mode_ptr;
157    int c;
158 
159    _farsetsel(_dos_ds);
160 
161    for (c=0; c<(int)sizeof(VESA_INFO); c++)
162       _farnspokeb(MASK_LINEAR(__tb)+c, 0);
163 
164    dosmemput("VBE2", 4, MASK_LINEAR(__tb));
165 
166    r.x.ax = 0x4F00;
167    r.x.di = RM_OFFSET(__tb);
168    r.x.es = RM_SEGMENT(__tb);
169    __dpmi_int(0x10, &r);
170    if (r.h.ah) {
171       printf("Int 0x10, ax=0x4F00 failed! ax=0x%02X\n", r.x.ax);
172       return -1;
173    }
174 
175    dosmemget(MASK_LINEAR(__tb), sizeof(VESA_INFO), &vesa_info);
176 
177    if (strncmp(vesa_info.VESASignature, "VESA", 4) != 0) {
178       printf("Bad VESA signature! (%4.4s)\n", vesa_info.VESASignature);
179       return -1;
180    }
181 
182    _farsetsel(_dos_ds);
183 
184    modes = 0;
185    mode_ptr = RM_TO_LINEAR(vesa_info.VideoModePtr);
186    mode[modes] = _farnspeekw(mode_ptr);
187 
188    while (mode[modes] != 0xFFFF) {
189       modes++;
190       mode_ptr += 2;
191       mode[modes] = _farnspeekw(mode_ptr);
192    }
193 
194    get_string(oem_string, vesa_info.OEMStringPtr);
195    get_string(oemvendor_string, vesa_info.OemVendorNamePtr);
196    get_string(oemproductname_string, vesa_info.OemProductNamePtr);
197    get_string(oemproductrev_string, vesa_info.OemProductRevPtr);
198 
199    printf("\n");
200 
201    printf("VESASignature:\t\t%4.4s\n", vesa_info.VESASignature);
202    printf("VESAVersion:\t\t%d.%d\n", vesa_info.VESAVersion>>8, vesa_info.VESAVersion&0xFF);
203    printf("OEMStringPtr:\t\t%s\n", oem_string);
204 
205    if (verbose) {
206       printf("Capabilities:\t\t%d (%s DAC | %s compatible | %s RAMDAC)\n",
207 	     vesa_info.Capabilities[0],
208 	     (vesa_info.Capabilities[0] & 1) ? "switchable" : "fixed",
209 	     (vesa_info.Capabilities[0] & 2) ? "not VGA" : "VGA",
210 	     (vesa_info.Capabilities[0] & 4) ? "vblank" : "normal");
211    }
212 
213    printf("TotalMemory:\t\t%d (%dK)\n", vesa_info.TotalMemory, vesa_info.TotalMemory*64);
214 
215    if (verbose) {
216       printf("OemSoftwareRev:\t\t%d.%d\n", vesa_info.OemSoftwareRev>>8, vesa_info.OemSoftwareRev&0xFF);
217       printf("OemVendorNamePtr:\t%s\n", oemvendor_string);
218       printf("OemProductNamePtr:\t%s\n", oemproductname_string);
219       printf("OemProductRevPtr:\t%s\n", oemproductrev_string);
220 
221       printf("\n\n\n");
222    }
223    else
224       printf("\n");
225 
226    return 0;
227 }
228 
229 
230 
231 int in_flag = FALSE;
232 
233 
234 
print_flag(char * s)235 void print_flag(char *s)
236 {
237    if (!in_flag) {
238       printf(" (");
239       in_flag = TRUE;
240    }
241    else
242       printf(" | ");
243 
244    printf(s);
245 }
246 
247 
248 
end_print_flag(void)249 void end_print_flag(void)
250 {
251    if (in_flag) {
252       printf(")\n");
253       in_flag = FALSE;
254    }
255    else
256       printf("\n");
257 }
258 
259 
260 
print_window_attributes(int attrib)261 void print_window_attributes(int attrib)
262 {
263    if (attrib & 1)
264       print_flag("moveable");
265 
266    if (attrib & 2)
267       print_flag("readable");
268 
269    if (attrib & 4)
270       print_flag("writable");
271 
272    end_print_flag();
273 }
274 
275 
276 
277 typedef struct COLORINFO
278 {
279    int size;
280    int pos;
281    char c;
282 } COLORINFO;
283 
284 COLORINFO colorinfo[4];
285 
286 int colorcount = 0;
287 
288 
289 
color_cmp(const void * e1,const void * e2)290 int color_cmp(const void *e1, const void *e2)
291 {
292    COLORINFO *c1 = (COLORINFO *)e1;
293    COLORINFO *c2 = (COLORINFO *)e2;
294 
295    return c2->pos - c1->pos;
296 }
297 
298 
299 
add_color(int size,int pos,char c)300 void add_color(int size, int pos, char c)
301 {
302    if ((size > 0) || (pos > 0)) {
303       colorinfo[colorcount].size = size;
304       colorinfo[colorcount].pos = pos;
305       colorinfo[colorcount].c = c;
306       colorcount++;
307    }
308 }
309 
310 
311 
get_color_desc(char * s)312 void get_color_desc(char *s)
313 {
314    int c;
315 
316    if (colorcount > 0) {
317       qsort(colorinfo, colorcount, sizeof(COLORINFO), color_cmp);
318 
319       for (c=0; c<colorcount; c++)
320 	 *(s++) = colorinfo[c].c;
321 
322       *(s++) = ' ';
323 
324       for (c=0; c<colorcount; c++)
325 	 *(s++) = '0' + colorinfo[c].size;
326 
327       colorcount = 0;
328    }
329 
330    *s = 0;
331 }
332 
333 
334 
get_mode_info(int mode)335 int get_mode_info(int mode)
336 {
337    __dpmi_regs r;
338    char color_desc[80];
339    int c;
340 
341    if (verbose)
342       printf("Mode 0x%X:\n\n", mode);
343    else
344       printf("Mode 0x%-3X: ", mode);
345 
346    _farsetsel(_dos_ds);
347 
348    for (c=0; c<(int)sizeof(MODE_INFO); c++)
349       _farnspokeb(MASK_LINEAR(__tb)+c, 0);
350 
351    r.x.ax = 0x4F01;
352    r.x.di = RM_OFFSET(__tb);
353    r.x.es = RM_SEGMENT(__tb);
354    r.x.cx = mode;
355    __dpmi_int(0x10, &r);
356    if (r.h.ah) {
357       printf("Int 0x10, ax=0x4F01 failed! ax=0x%02X\n", r.x.ax);
358       if (verbose)
359 	 printf("\n\n\n");
360       return -1;
361    }
362 
363    dosmemget(MASK_LINEAR(__tb), sizeof(MODE_INFO), &mode_info);
364 
365    add_color(mode_info.RedMaskSize, mode_info.RedMaskPos, 'R');
366    add_color(mode_info.GreenMaskSize, mode_info.GreenMaskPos, 'G');
367    add_color(mode_info.BlueMaskSize, mode_info.BlueMaskPos, 'B');
368    add_color(mode_info.ReservedMaskSize, mode_info.ReservedMaskPos, 'x');
369    get_color_desc(color_desc);
370 
371    if (verbose) {
372       printf("ModeAttributes:\t\t0x%X", mode_info.ModeAttributes);
373       if (mode_info.ModeAttributes & 1) print_flag("ok");
374       if (mode_info.ModeAttributes & 4) print_flag("tty");
375       if (mode_info.ModeAttributes & 8) print_flag("col"); else print_flag("mono");
376       if (mode_info.ModeAttributes & 16) print_flag("gfx"); else print_flag("text");
377       if (!(mode_info.ModeAttributes & 32)) print_flag("VGA");
378       if (!(mode_info.ModeAttributes & 64)) print_flag("bank");
379       if (mode_info.ModeAttributes & 128) print_flag("lfb");
380       if (mode_info.ModeAttributes & 1024) print_flag("3buf");
381       end_print_flag();
382 
383       printf("WinAAttributes:\t\t%d", mode_info.WinAAttributes);
384       print_window_attributes(mode_info.WinAAttributes);
385 
386       printf("WinBAttributes:\t\t%d", mode_info.WinBAttributes);
387       print_window_attributes(mode_info.WinBAttributes);
388 
389       printf("WinGranularity:\t\t%dK\n", mode_info.WinGranularity);
390       printf("WinSize:\t\t%dK\n", mode_info.WinSize);
391       printf("WinASegment:\t\t%X\n", mode_info.WinASegment);
392       printf("WinBSegment:\t\t%X\n", mode_info.WinBSegment);
393       printf("BytesPerScanLine:\t%d\n", mode_info.BytesPerScanLine);
394       printf("XResolution:\t\t%d\n", mode_info.XResolution);
395       printf("YResolution:\t\t%d\n", mode_info.YResolution);
396       printf("XCharSize:\t\t%d\n", mode_info.XCharSize);
397       printf("YCharSize:\t\t%d\n", mode_info.YCharSize);
398       printf("NumberOfPlanes:\t\t%d\n", mode_info.NumberOfPlanes);
399       printf("BitsPerPixel:\t\t%d\n", mode_info.BitsPerPixel);
400       printf("NumberOfBanks:\t\t%d\n", mode_info.NumberOfBanks);
401 
402       printf("MemoryModel:\t\t%d (", mode_info.MemoryModel);
403       switch (mode_info.MemoryModel) {
404 	 case 0:  printf("text"); break;
405 	 case 1:  printf("CGA"); break;
406 	 case 2:  printf("Hercules"); break;
407 	 case 3:  printf("planar"); break;
408 	 case 4:  printf("packed pixel"); break;
409 	 case 5:  printf("mode-X"); break;
410 	 case 6:  printf("direct color"); break;
411 	 case 7:  printf("YUV"); break;
412 	 default: printf("unknown"); break;
413       }
414       if (color_desc[0])
415 	 printf(" %s", color_desc);
416       printf(")\n");
417 
418       printf("BankSize:\t\t%d\n", mode_info.BankSize);
419       printf("NumberOfImagePages:\t%d\n", mode_info.NumberOfImagePages);
420       printf("Reserved_page:\t\t%d\n", mode_info.Reserved_page);
421       printf("RedMaskSize:\t\t%d\n", mode_info.RedMaskSize);
422       printf("RedMaskPos:\t\t%d\n", mode_info.RedMaskPos);
423       printf("GreenMaskSize:\t\t%d\n", mode_info.GreenMaskSize);
424       printf("GreenMaskPos:\t\t%d\n", mode_info.GreenMaskPos);
425       printf("BlueMaskSize:\t\t%d\n", mode_info.BlueMaskSize);
426       printf("BlueMaskPos:\t\t%d\n", mode_info.BlueMaskPos);
427       printf("ReservedMaskSize:\t%d\n", mode_info.ReservedMaskSize);
428       printf("ReservedMaskPos:\t%d\n", mode_info.ReservedMaskPos);
429 
430       printf("DirectColorModeInfo:\t%d (%s color ramp | %s reserved bits)\n",
431 	     mode_info.DirectColorModeInfo,
432 	     (mode_info.DirectColorModeInfo & 1) ? "programmable" : "fixed",
433 	     (mode_info.DirectColorModeInfo & 2) ? "can use" : "don't use");
434 
435       printf("PhysBasePtr:\t\t0x%08lX\n", mode_info.PhysBasePtr);
436       printf("OffScreenMemOffset:\t0x%08lX\n", mode_info.OffScreenMemOffset);
437       printf("OffScreenMemSize:\t%dK\n", mode_info.OffScreenMemSize);
438 
439       if (vesa_info.VESAVersion >= 0x300) {
440 	 printf("LinBytesPerScanLine:\t%d\n", mode_info.LinBytesPerScanLine);
441 	 printf("BnkNumberOfPages:\t%d\n", mode_info.BnkNumberOfPages);
442 	 printf("LinNumberOfPages:\t%d\n", mode_info.LinNumberOfPages);
443 	 printf("LinRedMaskSize:\t\t%d\n", mode_info.LinRedMaskSize);
444 	 printf("LinRedFieldPos:\t\t%d\n", mode_info.LinRedFieldPos);
445 	 printf("LinGreenMaskSize:\t%d\n", mode_info.LinGreenMaskSize);
446 	 printf("LinGreenFieldPos:\t%d\n", mode_info.LinGreenFieldPos);
447 	 printf("LinBlueMaskSize:\t%d\n", mode_info.LinBlueMaskSize);
448 	 printf("LinBlueFieldPos:\t%d\n", mode_info.LinBlueFieldPos);
449 	 printf("LinRsvdMaskSize:\t%d\n", mode_info.LinRsvdMaskSize);
450 	 printf("LinRsvdFieldPos:\t%d\n", mode_info.LinRsvdFieldPos);
451 	 printf("MaxPixelClock:\t\t%ld\n", mode_info.MaxPixelClock);
452       }
453 
454       printf("\n\n\n");
455    }
456    else {
457       printf("%5dx%-6d", mode_info.XResolution, mode_info.YResolution);
458       printf("%d bpp ", mode_info.BitsPerPixel);
459       switch (mode_info.MemoryModel) {
460 	 case 0:  printf("text"); break;
461 	 case 1:  printf("CGA"); break;
462 	 case 2:  printf("Hercules"); break;
463 	 case 3:  printf("planar"); break;
464 	 case 4:  printf("packed pixel"); break;
465 	 case 5:  printf("non-chain 4, 256 color"); break;
466 	 case 6:  printf("direct color"); break;
467 	 case 7:  printf("YUV"); break;
468 	 default: printf("unknown"); break;
469       }
470       if (color_desc[0])
471 	 printf(" (%s)", color_desc);
472       printf("\n");
473    }
474 
475    return 0;
476 }
477 
478 
479 
main(int argc,char * argv[])480 int main(int argc, char *argv[])
481 {
482    int c;
483 
484    if (allegro_init() != 0)
485       return -1;
486 
487    for (c=1; c<argc; c++)
488       if (((argv[c][0] == '-') || (argv[c][0] == '/')) &&
489 	  ((argv[c][1] == 'v') || (argv[c][1] == 'V')))
490 	 verbose = TRUE;
491 
492    printf("\nAllegro VESAINFO utility " ALLEGRO_VERSION_STR ", " ALLEGRO_PLATFORM_STR);
493    printf("\nBy Shawn Hargreaves, " ALLEGRO_DATE_STR "\n");
494    if (verbose)
495       printf("\n");
496 
497    if (get_vesa_info() != 0)
498       return -1;
499 
500    for (c=0; c<modes; c++)
501       get_mode_info(mode[c]);
502 
503    if (!verbose)
504       printf("\n'vesainfo -v' for a verbose listing\n\n");
505 
506    return 0;
507 }
508 
509 
510 
511 #else       /* ifdef ALLEGRO_DOS */
512 
513 
main(void)514 int main(void)
515 {
516    allegro_init();
517    allegro_message("Sorry, the VESAINFO program only works on DOS\n");
518    return 1;
519 }
520 
521 
522 #endif
523 
524 
525 END_OF_MAIN()
526