vidcontrol.c revision 42605
1288917Sroyger/*- 2288917Sroyger * Copyright (c) 1994-1996 S�ren Schmidt 3288917Sroyger * All rights reserved. 4288917Sroyger * 5288917Sroyger * Redistribution and use in source and binary forms, with or without 6288917Sroyger * modification, are permitted provided that the following conditions 7288917Sroyger * are met: 8288917Sroyger * 1. Redistributions of source code must retain the above copyright 9288917Sroyger * notice, this list of conditions and the following disclaimer, 10288917Sroyger * in this position and unchanged. 11288917Sroyger * 2. Redistributions in binary form must reproduce the above copyright 12288917Sroyger * notice, this list of conditions and the following disclaimer in the 13288917Sroyger * documentation and/or other materials provided with the distribution. 14288917Sroyger * 3. The name of the author may not be used to endorse or promote products 15288917Sroyger * derived from this software withough specific prior written permission 16288917Sroyger * 17288917Sroyger * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18288917Sroyger * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19288917Sroyger * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20288917Sroyger * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21288917Sroyger * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22288917Sroyger * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23288917Sroyger * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24288917Sroyger * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25288917Sroyger * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26288917Sroyger * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27288917Sroyger */ 28288917Sroyger 29288917Sroyger#ifndef lint 30288917Sroygerstatic const char rcsid[] = 31288917Sroyger "$Id: vidcontrol.c,v 1.25 1999/01/11 03:20:32 yokota Exp $"; 32288917Sroyger#endif /* not lint */ 33288917Sroyger 34288917Sroyger#include <ctype.h> 35288917Sroyger#include <err.h> 36288917Sroyger#include <stdio.h> 37288917Sroyger#include <stdlib.h> 38288917Sroyger#include <string.h> 39288917Sroyger#include <unistd.h> 40288917Sroyger#include <machine/console.h> 41288917Sroyger#include <sys/errno.h> 42288917Sroyger#include "path.h" 43288917Sroyger#include "decode.h" 44288917Sroyger 45288917Sroygerchar legal_colors[16][16] = { 46288917Sroyger "black", "blue", "green", "cyan", 47288917Sroyger "red", "magenta", "brown", "white", 48288917Sroyger "grey", "lightblue", "lightgreen", "lightcyan", 49288917Sroyger "lightred", "lightmagenta", "yellow", "lightwhite" 50}; 51int hex = 0; 52int number; 53char letter; 54struct vid_info info; 55 56 57static void 58usage() 59{ 60 fprintf(stderr, "%s\n%s\n%s\n", 61"usage: vidcontrol [-r fg bg] [-b color] [-c appearance] [-d] [-l scrmap]", 62" [-i adapter | mode] [-L] [-m on|off] [-f size file]", 63" [-s number] [-t N|off] [-x] [mode] [fgcol [bgcol]] [show]"); 64 exit(1); 65} 66 67char * 68nextarg(int ac, char **av, int *indp, int oc) 69{ 70 if (*indp < ac) 71 return(av[(*indp)++]); 72 errx(1, "option requires two arguments -- %c", oc); 73 return(""); 74} 75 76char * 77mkfullname(const char *s1, const char *s2, const char *s3) 78{ 79 static char *buf = NULL; 80 static int bufl = 0; 81 int f; 82 83 f = strlen(s1) + strlen(s2) + strlen(s3) + 1; 84 if (f > bufl) 85 if (buf) 86 buf = (char *)realloc(buf, f); 87 else 88 buf = (char *)malloc(f); 89 if (!buf) { 90 bufl = 0; 91 return(NULL); 92 } 93 94 bufl = f; 95 strcpy(buf, s1); 96 strcat(buf, s2); 97 strcat(buf, s3); 98 return(buf); 99} 100 101void 102load_scrnmap(char *filename) 103{ 104 FILE *fd = 0; 105 int i, size; 106 char *name; 107 scrmap_t scrnmap; 108 char *prefix[] = {"", "", SCRNMAP_PATH, SCRNMAP_PATH, NULL}; 109 char *postfix[] = {"", ".scm", "", ".scm"}; 110 111 for (i=0; prefix[i]; i++) { 112 name = mkfullname(prefix[i], filename, postfix[i]); 113 fd = fopen(name, "r"); 114 if (fd) 115 break; 116 } 117 if (fd == NULL) { 118 warn("screenmap file not found"); 119 return; 120 } 121 size = sizeof(scrnmap); 122 if (decode(fd, (char *)&scrnmap) != size) { 123 rewind(fd); 124 if (fread(&scrnmap, 1, size, fd) != size) { 125 warnx("bad screenmap file"); 126 fclose(fd); 127 return; 128 } 129 } 130 if (ioctl(0, PIO_SCRNMAP, &scrnmap) < 0) 131 warn("can't load screenmap"); 132 fclose(fd); 133} 134 135void 136load_default_scrnmap() 137{ 138 scrmap_t scrnmap; 139 int i; 140 141 for (i=0; i<256; i++) 142 *((char*)&scrnmap + i) = i; 143 if (ioctl(0, PIO_SCRNMAP, &scrnmap) < 0) 144 warn("can't load default screenmap"); 145} 146 147void 148print_scrnmap() 149{ 150 unsigned char map[256]; 151 int i; 152 153 if (ioctl(0, GIO_SCRNMAP, &map) < 0) { 154 warn("getting screenmap"); 155 return; 156 } 157 for (i=0; i<sizeof(map); i++) { 158 if (i > 0 && i % 16 == 0) 159 fprintf(stdout, "\n"); 160 if (hex) 161 fprintf(stdout, " %02x", map[i]); 162 else 163 fprintf(stdout, " %03d", map[i]); 164 } 165 fprintf(stdout, "\n"); 166 167} 168 169void 170load_font(char *type, char *filename) 171{ 172 FILE *fd = 0; 173 int i, size; 174 unsigned long io; 175 char *name, *fontmap; 176 char *prefix[] = {"", "", FONT_PATH, FONT_PATH, NULL}; 177 char *postfix[] = {"", ".fnt", "", ".fnt"}; 178 179 for (i=0; prefix[i]; i++) { 180 name = mkfullname(prefix[i], filename, postfix[i]); 181 fd = fopen(name, "r"); 182 if (fd) 183 break; 184 } 185 if (fd == NULL) { 186 warn("font file not found"); 187 return; 188 } 189 if (!strcmp(type, "8x8")) { 190 size = 8*256; 191 io = PIO_FONT8x8; 192 } 193 else if (!strcmp(type, "8x14")) { 194 size = 14*256; 195 io = PIO_FONT8x14; 196 } 197 else if (!strcmp(type, "8x16")) { 198 size = 16*256; 199 io = PIO_FONT8x16; 200 } 201 else { 202 warn("bad font size specification"); 203 fclose(fd); 204 return; 205 } 206 fontmap = (char*) malloc(size); 207 if (decode(fd, fontmap) != size) { 208 rewind(fd); 209 if (fread(fontmap, 1, size, fd) != size) { 210 warnx("bad font file"); 211 fclose(fd); 212 free(fontmap); 213 return; 214 } 215 } 216 if (ioctl(0, io, fontmap) < 0) 217 warn("can't load font"); 218 fclose(fd); 219 free(fontmap); 220} 221 222void 223set_screensaver_timeout(char *arg) 224{ 225 int nsec; 226 227 if (!strcmp(arg, "off")) 228 nsec = 0; 229 else { 230 nsec = atoi(arg); 231 if ((*arg == '\0') || (nsec < 1)) { 232 warnx("argument must be a positive number"); 233 return; 234 } 235 } 236 if (ioctl(0, CONS_BLANKTIME, &nsec) == -1) 237 warn("setting screensaver period"); 238} 239 240void 241set_cursor_type(char *appearence) 242{ 243 int type; 244 245 if (!strcmp(appearence, "normal")) 246 type = 0; 247 else if (!strcmp(appearence, "blink")) 248 type = 1; 249 else if (!strcmp(appearence, "destructive")) 250 type = 3; 251 else { 252 warnx("argument to -c must be normal, blink or destructive"); 253 return; 254 } 255 ioctl(0, CONS_CURSORTYPE, &type); 256} 257 258void 259video_mode(int argc, char **argv, int *index) 260{ 261 static struct { 262 char *name; 263 unsigned long mode; 264 } modes[] = { 265#ifdef SW_TEXT_80x25 266 { "80x25", SW_TEXT_80x25 }, 267 { "80x30", SW_TEXT_80x30 }, 268 { "80x43", SW_TEXT_80x43 }, 269 { "80x50", SW_TEXT_80x50 }, 270 { "80x60", SW_TEXT_80x60 }, 271 { "132x25", SW_TEXT_132x25 }, 272 { "132x30", SW_TEXT_132x30 }, 273 { "132x43", SW_TEXT_132x43 }, 274 { "132x50", SW_TEXT_132x50 }, 275 { "132x60", SW_TEXT_132x60 }, 276#endif 277 { "VGA_40x25", SW_VGA_C40x25 }, 278 { "VGA_80x25", SW_VGA_C80x25 }, 279 { "VGA_80x30", SW_VGA_C80x30 }, 280 { "VGA_80x50", SW_VGA_C80x50 }, 281 { "VGA_80x60", SW_VGA_C80x60 }, 282 { "VGA_320x200", SW_VGA_CG320 }, 283 { "EGA_80x25", SW_ENH_C80x25 }, 284 { "EGA_80x43", SW_ENH_C80x43 }, 285 { "VESA_132x25", SW_VESA_C132x25 }, 286 { "VESA_132x43", SW_VESA_C132x43 }, 287 { "VESA_132x50", SW_VESA_C132x50 }, 288 { "VESA_132x60", SW_VESA_C132x60 }, 289 { "VESA_800x600", SW_VESA_800x600 }, 290 { NULL }, 291 }; 292 unsigned long mode = 0; 293 int size[3]; 294 int i; 295 296 if (*index < argc) { 297 for (i = 0; modes[i].name != NULL; ++i) { 298 if (!strcmp(argv[*index], modes[i].name)) { 299 mode = modes[i].mode; 300 break; 301 } 302 } 303 if (modes[i].name == NULL) 304 return; 305 if (ioctl(0, mode, NULL) < 0) 306 warn("cannot set videomode"); 307 if (mode == SW_VESA_800x600) { 308 size[0] = 80; /* columns */ 309 size[1] = 25; /* rows */ 310 size[2] = 16; /* font size */ 311 if (ioctl(0, KDRASTER, size)) 312 warn("cannot activate raster display"); 313 } 314 (*index)++; 315 } 316 return; 317} 318 319int 320get_color_number(char *color) 321{ 322 int i; 323 324 for (i=0; i<16; i++) 325 if (!strcmp(color, legal_colors[i])) 326 return i; 327 return -1; 328} 329 330void 331set_normal_colors(int argc, char **argv, int *index) 332{ 333 int color; 334 335 if (*index < argc && (color = get_color_number(argv[*index])) != -1) { 336 (*index)++; 337 fprintf(stderr, "[=%dF", color); 338 if (*index < argc 339 && (color = get_color_number(argv[*index])) != -1 340 && color < 8) { 341 (*index)++; 342 fprintf(stderr, "[=%dG", color); 343 } 344 } 345} 346 347void 348set_reverse_colors(int argc, char **argv, int *index) 349{ 350 int color; 351 352 if ((color = get_color_number(argv[*(index)-1])) != -1) { 353 fprintf(stderr, "[=%dH", color); 354 if (*index < argc 355 && (color = get_color_number(argv[*index])) != -1 356 && color < 8) { 357 (*index)++; 358 fprintf(stderr, "[=%dI", color); 359 } 360 } 361} 362 363void 364set_console(char *arg) 365{ 366 int n; 367 368 if( !arg || strspn(arg,"0123456789") != strlen(arg)) { 369 warnx("bad console number"); 370 return; 371 } 372 373 n = atoi(arg); 374 if (n < 1 || n > 12) { 375 warnx("console number out of range"); 376 } else if (ioctl(0, VT_ACTIVATE, (caddr_t) (long) n) == -1) 377 warn("ioctl(VT_ACTIVATE)"); 378} 379 380void 381set_border_color(char *arg) 382{ 383 int color; 384 385 if ((color = get_color_number(arg)) != -1) { 386 fprintf(stderr, "[=%dA", color); 387 } 388 else 389 usage(); 390} 391 392void 393set_mouse(char *arg) 394{ 395 struct mouse_info mouse; 396 397 if (!strcmp(arg, "on")) 398 mouse.operation = MOUSE_SHOW; 399 else if (!strcmp(arg, "off")) 400 mouse.operation = MOUSE_HIDE; 401 else { 402 warnx("argument to -m must either on or off"); 403 return; 404 } 405 ioctl(0, CONS_MOUSECTL, &mouse); 406} 407 408static char 409*adapter_name(int type) 410{ 411 static struct { 412 int type; 413 char *name; 414 } names[] = { 415 { KD_MONO, "MDA" }, 416 { KD_HERCULES, "Hercules" }, 417 { KD_CGA, "CGA" }, 418 { KD_EGA, "EGA" }, 419 { KD_VGA, "VGA" }, 420 { KD_PC98, "PC-98xx" }, 421 { -1, "Unknown" }, 422 }; 423 int i; 424 425 for (i = 0; names[i].type != -1; ++i) 426 if (names[i].type == type) 427 break; 428 return names[i].name; 429} 430 431void 432show_adapter_info(void) 433{ 434#ifdef __i386__ 435 struct video_adapter_info ad; 436#else 437 struct video_adapter ad; 438#endif 439 440 ad.va_index = 0; 441 if (ioctl(0, CONS_ADPINFO, &ad)) { 442 warn("failed to obtain adapter information"); 443 return; 444 } 445 446 printf("fb%d:\n", ad.va_index); 447#ifdef __i386__ 448 printf(" %.*s%d, type:%s%s (%d), flags:0x%x\n", 449 (int)sizeof(ad.va_name), ad.va_name, ad.va_unit, 450#else 451 printf(" type:%s%s (%d), flags:0x%x\n", 452#endif 453 (ad.va_flags & V_ADP_VESA) ? "VESA " : "", 454 adapter_name(ad.va_type), ad.va_type, ad.va_flags); 455 printf(" initial mode:%d, current mode:%d, BIOS mode:%d\n", 456 ad.va_initial_mode, ad.va_mode, ad.va_initial_bios_mode); 457} 458 459void 460show_mode_info(void) 461{ 462 struct video_info info; 463 char buf[80]; 464 int mode; 465 int c; 466 467 printf(" mode# flags type size " 468 "font window linear buffer\n"); 469 printf("---------------------------------------" 470 "---------------------------------------\n"); 471 for (mode = 0; mode < M_VESA_MODE_MAX; ++mode) { 472 info.vi_mode = mode; 473 if (ioctl(0, CONS_MODEINFO, &info)) 474 continue; 475 476 printf("%3d (0x%03x)", mode, mode); 477 printf(" 0x%08x", info.vi_flags); 478 if (info.vi_flags & V_INFO_GRAPHICS) { 479 c = 'G'; 480 snprintf(buf, sizeof(buf), "%dx%dx%d %d", 481 info.vi_width, info.vi_height, 482 info.vi_depth, info.vi_planes); 483 } else { 484 c = 'T'; 485 snprintf(buf, sizeof(buf), "%dx%d", 486 info.vi_width, info.vi_height); 487 } 488 printf(" %c %-15s", c, buf); 489 snprintf(buf, sizeof(buf), "%dx%d", 490 info.vi_cwidth, info.vi_cheight); 491 printf(" %-5s", buf); 492 printf(" 0x%05x %2dk %2dk", 493 info.vi_window, info.vi_window_size/1024, 494 info.vi_window_gran/1024); 495 printf(" 0x%08x %2dk\n", 496 info.vi_buffer, info.vi_buffer_size/1024); 497 } 498} 499 500void 501show_info(char *arg) 502{ 503 if (!strcmp(arg, "adapter")) 504 show_adapter_info(); 505 else if (!strcmp(arg, "mode")) 506 show_mode_info(); 507 else { 508 warnx("argument to -i must either adapter or mode"); 509 return; 510 } 511} 512 513void 514test_frame() 515{ 516 int i; 517 518 fprintf(stdout, "[=0G\n\n"); 519 for (i=0; i<8; i++) { 520 fprintf(stdout, "[=15F[=0G %2d [=%dF%-16s" 521 "[=15F[=0G %2d [=%dF%-16s " 522 "[=15F %2d [=%dGBACKGROUND[=0G\n", 523 i, i, legal_colors[i], i+8, i+8, 524 legal_colors[i+8], i, i); 525 } 526 fprintf(stdout, "[=%dF[=%dG[=%dH[=%dI\n", 527 info.mv_norm.fore, info.mv_norm.back, 528 info.mv_rev.fore, info.mv_rev.back); 529} 530 531int 532main(int argc, char **argv) 533{ 534 int opt; 535 536 537 info.size = sizeof(info); 538 if (ioctl(0, CONS_GETINFO, &info) < 0) 539 err(1, "must be on a virtual console"); 540 while((opt = getopt(argc, argv, "b:c:df:i:l:Lm:r:s:t:x")) != -1) 541 switch(opt) { 542 case 'b': 543 set_border_color(optarg); 544 break; 545 case 'c': 546 set_cursor_type(optarg); 547 break; 548 case 'd': 549 print_scrnmap(); 550 break; 551 case 'f': 552 load_font(optarg, 553 nextarg(argc, argv, &optind, 'f')); 554 break; 555 case 'i': 556 show_info(optarg); 557 break; 558 case 'l': 559 load_scrnmap(optarg); 560 break; 561 case 'L': 562 load_default_scrnmap(); 563 break; 564 case 'm': 565 set_mouse(optarg); 566 break; 567 case 'r': 568 set_reverse_colors(argc, argv, &optind); 569 break; 570 case 's': 571 set_console(optarg); 572 break; 573 case 't': 574 set_screensaver_timeout(optarg); 575 break; 576 case 'x': 577 hex = 1; 578 break; 579 default: 580 usage(); 581 } 582 video_mode(argc, argv, &optind); 583 set_normal_colors(argc, argv, &optind); 584 if (optind < argc && !strcmp(argv[optind], "show")) { 585 test_frame(); 586 optind++; 587 } 588 if ((optind != argc) || (argc == 1)) 589 usage(); 590 return 0; 591} 592 593