--- /dev/null
+/*----------------------------------------------------------------------------\r
+Sets text video modes\r
+Chris Giese <geezer@execpc.com> http://my.execpc.com/~geezer/\r
+This code is public domain (no copyright).\r
+You can do whatever you want with it.\r
+Release date: March 31, 2009\r
+\r
+Compile with Turbo C, Borland C for DOS, or 16-bit Watcom C. I used:\r
+ bcc -O2 -2 -Z -d -mt -f- -w -c setres.c\r
+ tlink /Lc:\bc\lib /x/t c0t.obj setres.obj,setres.com,,cs.lib\r
+\r
+On one of my systems, the following video modes are supported:\r
+ 40x25[b ] 40x50[b ] 80x25[b ] 80x50[b ] 132x25[v ] 132x43[v ]\r
+ 40x30[tb] 40x60[tb] 80x30[tb] 80x60[tb] 90x25[tb] 90x30[tb]\r
+ 90x50[tb] 90x60[tb] 132x30[tv] 132x50[tv] 132x60[tv]\r
+\r
+[ b]=VGA BIOS (INT 10h AH=00h) modes [tb]=tweaked VGA BIOS modes\r
+[ v]=VBE BIOS (INT 10h AX=4F0xh) modes [tv]=tweaked VBE BIOS modes\r
+\r
+The 'tweaked' modes start with a VGA or VBE BIOS mode, then write to the\r
+CRTC registers to change the resolution. By default, this will happen only\r
+if INT 10h AX=4F00h reports that the hardware is register-compatible with\r
+VGA and INT 10h AX=4F01h reports that the mode is also register-compatible\r
+with VGA. '-v' option overrides this -- use it at your own risk. Tweaking\r
+does not (should not?) change the sync frequencies to unsupported values.\r
+----------------------------------------------------------------------------*/\r
+#include <string.h> /* strcpy() */\r
+#include <stdlib.h> /* realloc(), atoi() */\r
+#include <stdio.h> /* printf(), putchar() */\r
+#include <ctype.h> /* tolower() */\r
+/* union REGS, struct SREGS, int86(), int86x(), FP_SEG(), FP_OFF(), */\r
+#include <dos.h> /* pokeb(), poke(), inportb(), outportb() */\r
+#if 0\r
+#include <stdint.h>\r
+#else\r
+typedef unsigned char uint8_t;\r
+typedef unsigned short uint16_t;\r
+typedef unsigned long uint32_t;\r
+#endif\r
+\r
+#if defined(__TURBOC__)\r
+#include <conio.h> /* clrscr() */\r
+\r
+#elif defined(__WATCOMC__)\r
+#if defined(__386__)\r
+#error 16-bit program -- compile with WCC.EXE\r
+#endif\r
+#define inportb(P) inp(P)\r
+#define outportb(P,V) outp(P,V)\r
+#define pokeb(S,O,V) *(uint8_t far *)MK_FP(S,O)=(V)\r
+#define poke(S,O,V) *(uint16_t far *)MK_FP(S,O)=(V)\r
+#define peek(S,O) *(uint16_t far *)MK_FP(S,O)\r
+void clrscr(void)\r
+{\r
+ union REGS regs;\r
+\r
+ regs.h.ah = 0x02;\r
+ regs.h.bh = 0; /* page number */\r
+ regs.h.dh = 0; /* top-most row */\r
+ regs.h.dl = 0; /* left-most column */\r
+ int86(0x10, ®s, ®s);\r
+}\r
+\r
+#else\r
+#error Sorry, unsupported compiler\r
+#endif\r
+\r
+/* besides the CRTC, VGA sequencer register #1 is also modified */\r
+#define VGA_SEQ_INDEX 0x3C4\r
+#define VGA_SEQ_DATA 0x3C5\r
+/* emulation (color or mono) is read from this register --\r
+it determines the CRTC I/O address (0x3B4 or 0x3D4) */\r
+#define VGA_MISC_READ 0x3CC\r
+#define VGA_CRTC_INDEX (g_crtc_io + 0)\r
+#define VGA_CRTC_DATA (g_crtc_io + 1)\r
+\r
+/* this is like an X11 "modeline" */\r
+typedef struct\r
+{\r
+ unsigned disp, blank_start, sync_start, sync_end, blank_end, total;\r
+} timing_t;\r
+\r
+/* for 30-line modes, use the 16-pixel-high font instead of 8-pixel */\r
+static timing_t g_60_lines =\r
+{\r
+/* blank sync sync blank\r
+ disp start start end end tot\r
+ ---- ----- ----- ---- ----- --- */\r
+ 480, 488, 490, 493, 517, 525\r
+};\r
+\r
+static timing_t g_90_cols =\r
+{\r
+/* blank sync sync blank\r
+ disp start start end end tot\r
+ ---- ----- ----- ---- ----- --- */\r
+ 90, 90, 95, 108, 98, 112\r
+};\r
+\r
+typedef struct\r
+{\r
+ unsigned char cols, rows;\r
+ unsigned mode_num; /* VGA (<0x100) or VBE (>=0x100) mode number */\r
+ unsigned char set_font; /* set 8x8 font after mode-set or no? */\r
+ timing_t *horiz, *vert; /* CRTC timing 'tweaks' */\r
+} mode_t;\r
+\r
+static mode_t *g_mode;\r
+static unsigned g_crtc_io, g_num_modes;\r
+/*****************************************************************************\r
+*****************************************************************************/\r
+static void add_mode(unsigned cols, unsigned rows, unsigned mode_num,\r
+ unsigned set_font, timing_t *horiz, timing_t *vert)\r
+{\r
+ mode_t *new_mode;\r
+\r
+ new_mode = realloc(g_mode, (g_num_modes + 1) * sizeof(mode_t));\r
+ if(new_mode == NULL)\r
+ {\r
+ printf("Error: out of memory\n");\r
+ exit(2);\r
+ }\r
+ g_mode = new_mode;\r
+ new_mode = &g_mode[g_num_modes];\r
+ g_num_modes++;\r
+ new_mode->cols = cols;\r
+ new_mode->rows = rows;\r
+ new_mode->mode_num = mode_num;\r
+ new_mode->set_font = set_font;\r
+ new_mode->horiz = horiz;\r
+ new_mode->vert = vert;\r
+}\r
+/*****************************************************************************\r
+*****************************************************************************/\r
+static void dump_modes(void)\r
+{\r
+ unsigned scn_wd, csr_x, i;\r
+ union REGS regs;\r
+\r
+ scn_wd = peek(0x40, 0x4A);\r
+ printf("The following video modes are supported\n");\r
+ for(i = 0; i < g_num_modes; i++)\r
+ {\r
+/* get cursor X position */\r
+ regs.h.ah = 0x03;\r
+ regs.h.bh = 0;\r
+ int86(0x10, ®s, ®s);\r
+ csr_x = regs.h.dl;\r
+/* emit newline now if next listing will wrap */\r
+ if(csr_x + 7 >= scn_wd)\r
+ printf("\n");\r
+/* resolution listing is 7 characters wide */\r
+ printf("%4ux%-2u ", g_mode[i].cols, g_mode[i].rows);\r
+ }\r
+ printf("\n");\r
+}\r
+/*****************************************************************************\r
+*****************************************************************************/\r
+static mode_t *find_mode(unsigned cols, unsigned rows)\r
+{\r
+ unsigned i;\r
+\r
+ for(i = 0; i < g_num_modes; i++)\r
+ {\r
+ if(g_mode[i].cols == cols && g_mode[i].rows == rows)\r
+ return &g_mode[i];\r
+ }\r
+ return NULL;\r
+}\r
+/*****************************************************************************\r
+*****************************************************************************/\r
+static void set_horiz(timing_t *t)\r
+{\r
+ unsigned i;\r
+\r
+/* remove write-protection from CRTC registers 0-5 (and 6-7) */\r
+ outportb(VGA_CRTC_INDEX, 17);\r
+ outportb(VGA_CRTC_DATA, inportb(VGA_CRTC_DATA) & ~0x80);\r
+/* set horizontal displayed */\r
+ outportb(VGA_CRTC_INDEX, 1);\r
+ outportb(VGA_CRTC_DATA, t->disp - 1);\r
+/* set horizontal blanking start */\r
+ outportb(VGA_CRTC_INDEX, 2);\r
+ outportb(VGA_CRTC_DATA, t->blank_start);\r
+/* set horizontal sync start */\r
+ outportb(VGA_CRTC_INDEX, 4);\r
+ outportb(VGA_CRTC_DATA, t->sync_start);\r
+/* set horizontal sync end */\r
+ outportb(VGA_CRTC_INDEX, 5);\r
+ i = inportb(VGA_CRTC_DATA) & ~0x1F;\r
+ outportb(VGA_CRTC_DATA, (t->sync_end & 0x1F) | i);\r
+/* set horizontal blanking end */\r
+ outportb(VGA_CRTC_INDEX, 3);\r
+ i = inportb(VGA_CRTC_DATA) & ~0x1F;\r
+ outportb(VGA_CRTC_DATA, (t->blank_end & 0x1F) | i);\r
+/* set horizontal total */\r
+ outportb(VGA_CRTC_INDEX, 0);\r
+ outportb(VGA_CRTC_DATA, t->total - 5);\r
+/* set "offset" (words per line) */\r
+ outportb(VGA_CRTC_INDEX, 19);\r
+ outportb(VGA_CRTC_DATA, t->disp / 2);\r
+/* make characters 8 or 9 pixels wide */\r
+ outportb(VGA_SEQ_INDEX, 1);\r
+ i = inportb(VGA_SEQ_DATA) & ~0x01;\r
+ if(t->disp == 90)\r
+ i |= 0x01;\r
+ outportb(VGA_SEQ_DATA, i);\r
+}\r
+/*****************************************************************************\r
+*****************************************************************************/\r
+static void set_vert(timing_t *t)\r
+{\r
+ unsigned i, j;\r
+\r
+/* remove write-protection from CRTC registers 6-7 (and 0-5) */\r
+ outportb(VGA_CRTC_INDEX, 17);\r
+ outportb(VGA_CRTC_DATA, inportb(VGA_CRTC_DATA) & ~0x80);\r
+/* set vertical displayed */\r
+ i = t->disp - 1;\r
+ outportb(VGA_CRTC_INDEX, 18);\r
+ outportb(VGA_CRTC_DATA, i);\r
+ outportb(VGA_CRTC_INDEX, 7);\r
+ j = inportb(VGA_CRTC_DATA) & ~0x42;\r
+ if(i & 0x100)\r
+ j |= 0x02;\r
+ if(i & 0x200)\r
+ j |= 0x40;\r
+ outportb(VGA_CRTC_DATA, j);\r
+/* set vertical blanking start */\r
+ i = t->blank_start;\r
+ outportb(VGA_CRTC_INDEX, 21);\r
+ outportb(VGA_CRTC_DATA, i);\r
+ outportb(VGA_CRTC_INDEX, 7);\r
+ j = inportb(VGA_CRTC_DATA) & ~0x08;\r
+ if(i & 0x100)\r
+ j |= 0x08;\r
+ outportb(VGA_CRTC_DATA, j);\r
+/* set vertical sync (retrace) start */\r
+ i = t->sync_start;\r
+ outportb(VGA_CRTC_INDEX, 16);\r
+ outportb(VGA_CRTC_DATA, i);\r
+ outportb(VGA_CRTC_INDEX, 7);\r
+ j = inportb(VGA_CRTC_DATA) & ~0x84;\r
+ if(i & 0x100)\r
+ j |= 0x04;\r
+ if(i & 0x200)\r
+ j |= 0x80;\r
+ outportb(VGA_CRTC_DATA, j);\r
+/* set vertical sync (retrace) end */\r
+ outportb(VGA_CRTC_INDEX, 17);\r
+ i = inportb(VGA_CRTC_DATA) & ~0x0F;\r
+ outportb(VGA_CRTC_DATA, (t->sync_end & 0x0F) | i);\r
+/* set vertical blanking end */\r
+ outportb(VGA_CRTC_INDEX, 22);\r
+/* i = inportb(VGA_CRTC_DATA) & ~0x7F;\r
+ outportb(VGA_CRTC_DATA, (t->blank_end & 0x7F) | i); */\r
+ outportb(VGA_CRTC_DATA, t->blank_end);\r
+/* set vertical total */\r
+ i = t->total - 2;\r
+ outportb(VGA_CRTC_INDEX, 6);\r
+ outportb(VGA_CRTC_DATA, i);\r
+ outportb(VGA_CRTC_INDEX, 7);\r
+ j = inportb(VGA_CRTC_DATA) & ~0x21;\r
+ if(i & 0x100)\r
+ j |= 0x01;\r
+ if(i & 0x200)\r
+ j |= 0x20;\r
+ outportb(VGA_CRTC_DATA, j);\r
+}\r
+/*****************************************************************************\r
+*****************************************************************************/\r
+static void set_mode(mode_t *m)\r
+{\r
+ union REGS regs;\r
+\r
+/* set (initial) mode; using either the VGA... */\r
+ if(m->mode_num < 0x100)\r
+ {\r
+ regs.x.ax = m->mode_num;\r
+ int86(0x10, ®s, ®s);\r
+ }\r
+/* ...or VBE BIOS */\r
+ else\r
+ {\r
+ regs.x.ax = 0x4F02;\r
+ regs.x.bx = m->mode_num;\r
+ int86(0x10, ®s, ®s);\r
+ }\r
+/* set 8x8 font for 50- and 60-row VGA and tweaked modes */\r
+ if(m->set_font)\r
+ {\r
+ regs.x.ax = 0x1112;\r
+ regs.h.bl = 0;\r
+ int86(0x10, ®s, ®s);\r
+ }\r
+ if(m->horiz || m->vert)\r
+ {\r
+/* get CRTC address */\r
+ if((inportb(VGA_MISC_READ) & 0x01) == 0)\r
+ g_crtc_io = 0x3B4; /* monochrome emulation */\r
+ else\r
+ g_crtc_io = 0x3D4; /* color emulation */\r
+/* tweak CRTC timing */\r
+ if(m->horiz)\r
+ set_horiz(m->horiz);\r
+ if(m->vert)\r
+ set_vert(m->vert);\r
+ }\r
+/* let the BIOS know what we've done so text output works properly */\r
+ pokeb(0x40, 0x84, m->rows - 1);\r
+ poke(0x40, 0x4A, m->cols);\r
+}\r
+/*****************************************************************************\r
+*****************************************************************************/\r
+static void usage(void)\r
+{\r
+ printf("Sets text video modes. Usage:\n"\r
+ "\tSETRES [-vd] cols rows\t\t" "-v skips VGA compatability test\n"\r
+ "\t\t\t\t\t" "-d prints debug messages\n"\r
+ "\tSETRES -l[vd]\t\t\t" "lists available modes\n"\r
+ "\tSETRES -a\t\t\t" "displays author info\n");\r
+ exit(1);\r
+}\r
+/*****************************************************************************\r
+*****************************************************************************/\r
+int main(int arg_c, char *arg_v[])\r
+{\r
+/* structure used by INT 10h AX=4F00h */\r
+#pragma pack(1)\r
+ static struct\r
+ {\r
+ char sig[4];\r
+ uint8_t ver_minor;\r
+ uint8_t ver_major;\r
+ char far *oem_name;\r
+ uint32_t capabilities; /* b1=1 for non-VGA board */\r
+ uint16_t far *mode_list;\r
+ char res0[494]; /* fields we don't care about */\r
+ } vbe_info;\r
+/* structure used by INT 10h AX=4F01h */\r
+#pragma pack(1)\r
+ static struct\r
+ {\r
+ uint16_t mode_attrib; /* b4=0 for text modes */\r
+ char res0[16]; /* fields we don't care about */\r
+/* OEM modes and VBE 1.2+ only: */\r
+ uint16_t wd;\r
+ uint16_t ht;\r
+ uint8_t char_wd;\r
+ uint8_t char_ht;\r
+ char res1[232]; /* fields we don't care about */\r
+ } mode_info;\r
+/* command-line options: */\r
+ char assume_vga, list_modes, info, debug;\r
+ unsigned i, num_count, wd, ht;\r
+ uint16_t far *mnp; /* Mode Number Pointer */\r
+ struct SREGS sregs;\r
+ union REGS regs;\r
+ mode_t *mode;\r
+ char *s;\r
+\r
+/* process command-line */\r
+ if(arg_c < 2)\r
+ usage();\r
+ num_count = 0;\r
+ assume_vga = list_modes = info = debug = 0;\r
+ for(i = 1; i < arg_c; i++)\r
+ {\r
+/* options */\r
+ if(arg_v[i][0] == '-')\r
+ {\r
+ for(s = &arg_v[i][1]; *s != '\0'; s++)\r
+ {\r
+ if(tolower(*s) == 'v')\r
+ assume_vga = 1;\r
+ else if(tolower(*s) == 'l')\r
+ list_modes = 1;\r
+ else if(tolower(*s) == 'a')\r
+ info = 1;\r
+ else if(tolower(*s) == 'd')\r
+ debug = 1;\r
+ else\r
+ {\r
+ printf("Error: invalid option '%c'\n",\r
+ *s);\r
+ usage();\r
+ }\r
+ }\r
+ }\r
+/* not an option, not a number */\r
+ else if(atoi(arg_v[i]) == 0)\r
+ {\r
+ printf("Error: invalid parameter '%s'\n", arg_v[i]);\r
+ usage();\r
+ }\r
+/* 1st number on command line = rows */\r
+ else if(num_count == 0)\r
+ {\r
+ wd = atoi(arg_v[i]);\r
+ num_count++;\r
+ }\r
+/* 2nd number on command line = cols */\r
+ else if(num_count == 1)\r
+ {\r
+ ht = atoi(arg_v[i]);\r
+ num_count++;\r
+ }\r
+/* too many numbers */\r
+ else\r
+ {\r
+ printf("Error: invalid parameter '%s'\n", arg_v[i]);\r
+ usage();\r
+ }\r
+ }\r
+ if(info)\r
+ {\r
+ printf( "Sets text video modes\n"\r
+ "Chris Giese <geezer@execpc.com> http://my.execpc.com/~geezer/\n"\r
+ "This code is public domain (no copyright).\n"\r
+ "You can do whatever you want with it.\n"\r
+ "Release date: March 31, 2009\n");\r
+ return 1;\r
+ }\r
+/* I assume these VGA text modes are supported on all systems: */\r
+ if(debug)\r
+ printf("Adding VGA BIOS modes...\n");\r
+ add_mode(40, 25, 1, 0, NULL, NULL);\r
+ add_mode(40, 50, 1, 1, NULL, NULL);\r
+ add_mode(80, 25, 3, 0, NULL, NULL);\r
+ add_mode(80, 50, 3, 1, NULL, NULL);\r
+/* check if VBE present */\r
+ if(debug)\r
+ printf("VBE BIOS...");\r
+ strcpy(vbe_info.sig, "VBE2");\r
+ sregs.es = FP_SEG(&vbe_info);\r
+ regs.x.di = FP_OFF(&vbe_info);\r
+ regs.x.ax = 0x4F00;\r
+ int86x(0x10, ®s, ®s, &sregs);\r
+/* (the indentation got a little ugly, so I'm going to use goto)\r
+need VBE 1.2 or better */\r
+ if(regs.x.ax != 0x004F)\r
+ {\r
+ if(debug)\r
+ printf("not detected\n");\r
+ goto NO_VBE;\r
+ }\r
+ if(debug)\r
+ printf("version %u.%u; OEM name '%Fs'\n", vbe_info.ver_major,\r
+ vbe_info.ver_minor,vbe_info.oem_name);\r
+ if(vbe_info.ver_major < 1 ||\r
+ (vbe_info.ver_major == 1 && vbe_info.ver_minor < 2))\r
+ {\r
+ if(debug)\r
+ printf("Warning: VBE 1.2+ required\n");\r
+ goto NO_VBE;\r
+ }\r
+/* iterate over VBE modes */\r
+ if(debug)\r
+ printf("Hex VBE mode numbers:\n");\r
+ for(mnp = vbe_info.mode_list; *mnp != 0xFFFF; mnp++)\r
+ {\r
+ if(debug)\r
+ printf("%4X ", *mnp);\r
+/* get mode info */\r
+ sregs.es = FP_SEG(&mode_info);\r
+ regs.x.di = FP_OFF(&mode_info);\r
+ regs.x.cx = *mnp;\r
+ regs.x.ax = 0x4F01;\r
+ int86x(0x10, ®s, ®s, &sregs);\r
+ if(regs.x.ax != 0x004F)\r
+ continue;\r
+/* ignore all but text modes */\r
+ if(mode_info.mode_attrib & 0x10)\r
+ continue;\r
+/* add VBE text mode to list */\r
+ if(debug)\r
+ printf("\nAdding VBE mode: %ux%u\n",\r
+ mode_info.wd, mode_info.ht);\r
+ add_mode(mode_info.wd, mode_info.ht, *mnp, 0, NULL, NULL);\r
+ }\r
+ if(debug)\r
+ {\r
+ if(assume_vga)\r
+ printf("\n-v option; assuming hardware is VGA-compatible\n");\r
+ else\r
+ {\r
+ printf("\nHardware is ");\r
+ if(vbe_info.capabilities & 0x01)\r
+ printf("NOT ");\r
+ printf("register-compatible with VGA\n");\r
+ }\r
+ }\r
+/* check if board is register-compatible with VGA\r
+(unless overriden with '-v' option...) */\r
+ if(!assume_vga && (vbe_info.capabilities & 0x01))\r
+ goto NO_VBE;\r
+/* add 'tweaked' VGA modes to list */\r
+ if(debug)\r
+ printf("Adding tweaked VGA modes...\n");\r
+ add_mode(40, 30, 1, 0, NULL, &g_60_lines);\r
+ add_mode(40, 60, 1, 1, NULL, &g_60_lines);\r
+ add_mode(80, 30, 3, 0, NULL, &g_60_lines);\r
+ add_mode(80, 60, 3, 1, NULL, &g_60_lines);\r
+ add_mode(90, 25, 3, 0, &g_90_cols, NULL);\r
+ add_mode(90, 30, 3, 0, &g_90_cols, &g_60_lines);\r
+ add_mode(90, 50, 3, 1, &g_90_cols, NULL);\r
+ add_mode(90, 60, 3, 1, &g_90_cols, &g_60_lines);\r
+/* prepare to tweak VBE modes */\r
+ for(i = 0; i < g_num_modes; i++)\r
+ {\r
+ static unsigned rows[] = { 25, 30, 50, 60 };\r
+/**/\r
+ unsigned j, set_font, tweak_vert;\r
+\r
+/* find VBE modes... */\r
+ if(g_mode[i].mode_num < 0x100)\r
+ continue;\r
+/* ...with 25, 30, 50, or 60 rows */\r
+ if(g_mode[i].rows != 25 && g_mode[i].rows != 30\r
+ && g_mode[i].rows != 50 && g_mode[i].rows != 60)\r
+ continue;\r
+/* check if this mode is register-compatible with VGA */\r
+ if(!assume_vga)\r
+ {\r
+ sregs.es = FP_SEG(&mode_info);\r
+ regs.x.di = FP_OFF(&mode_info);\r
+ regs.x.cx = g_mode[i].mode_num;\r
+ regs.x.ax = 0x4F01;\r
+ int86x(0x10, ®s, ®s, &sregs);\r
+ if(regs.x.ax != 0x004F)\r
+ continue;\r
+/* xxx - b5 of mode_info.mode_attrib may be VBE 2.0+ only,\r
+according to Ralf Brown's list */\r
+ if(mode_info.mode_attrib & 0x20)\r
+ {\r
+ if(debug)\r
+ printf("VBE mode 0x%X is NOT "\r
+ "register-compatible with "\r
+ "VGA; will not tweak\n",\r
+ g_mode[i].mode_num);\r
+ continue;\r
+ }\r
+ }\r
+/* now find mode with same number of columns\r
+and complementary number of rows */\r
+ for(j = 0; j < sizeof(rows) / sizeof(rows[0]); j++)\r
+ {\r
+ if(g_mode[i].rows == rows[j])\r
+ continue;\r
+/* if the complementary mode does not already exist... */\r
+ mode = find_mode(g_mode[i].cols, rows[j]);\r
+ if(mode != NULL)\r
+ continue;\r
+/* ...add it */\r
+ set_font = (rows[j] >= 50);\r
+ tweak_vert = (rows[j] == 30 || rows[j] == 60);\r
+ if(debug)\r
+ printf("Adding tweaked VBE mode: %ux%u\n",\r
+ g_mode[i].cols, rows[j]);\r
+ add_mode(g_mode[i].cols, rows[j],\r
+ g_mode[i].mode_num, set_font, NULL,\r
+ (tweak_vert ? &g_60_lines : NULL));\r
+ }\r
+ }\r
+NO_VBE:\r
+/* just list the supported modes */\r
+ if(list_modes)\r
+ {\r
+ dump_modes();\r
+ return 0;\r
+ }\r
+/* otherwise we need two numbers on the command-line\r
+(the case of more than 2 numbers was handled above) */\r
+ if(num_count != 2)\r
+ {\r
+ printf("Error: must specify cols and rows to set video mode\n");\r
+ usage();\r
+ }\r
+/* see if selected resolution supported */\r
+ mode = find_mode(wd, ht);\r
+ if(mode == NULL)\r
+ {\r
+ printf("Error: mode %ux%u not supported\n", wd, ht);\r
+ dump_modes();\r
+ return 3;\r
+ }\r
+/* SET MODE */\r
+ set_mode(mode);\r
+#if 1\r
+/* clear screen */\r
+ clrscr();\r
+#else\r
+/* DEBUG: display horizontal and vertical 'rulers' */\r
+/* textattr(0x17); doesn't work -- no blue background after clrscr() */\r
+ clrscr();\r
+ for(i = 1; i < 0xFF00; i += 2)\r
+ pokeb(0xB800, i, 0x17);\r
+ for(i = 0; i < wd - 1; )\r
+ {\r
+ if(i % 10 == 0)\r
+ {\r
+ printf("%03u", i);\r
+ i += 3;\r
+ }\r
+ else\r
+ {\r
+ putchar(' ');\r
+ i++;\r
+ }\r
+ }\r
+ putchar('\n');\r
+ for(i = 1; i < ht - 4; i++)\r
+ printf("%u\n", i);\r
+ printf("Current screen resolution is %ux%u\n", wd, ht);\r
+#endif\r
+ return 0;\r
+}\r