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