├── LICENSE ├── README.md └── vgapal.c /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Noah Johnson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vgapal 2 | Generate the default VGA 256-color palette. 3 | 4 | This is the palette that would be initially loaded in the Digital 5 | Analog Converters (DACs) when a VGA card is switched into 256-color 6 | Mode 13h using the VGA BIOS at interrupt 10h. 7 | 8 | VGA cards used 6 bits per RGB channel in the DACs, so the intensity 9 | levels of red, green, and blue components range from 0-63 decimal, 10 | rather than the more typical modern 8-bit range of 0-255. The VGAPAL 11 | program is able to upconvert from the original 6-bit components to 12 | 8-bit components by shifting 6-bit component values two bits to the 13 | left and duplicating the two most significant bits as the two least 14 | significant bits. Hence, the VGAPAL program can generate both the 15 | original 64-level (6-bit) RGB palette, and a modernized 256-level 16 | (8-bit) RGB palette. 17 | 18 | The VGAPAL program generates a 64-level (6-bit) 256-color palette that 19 | exactly matches the "default_palette" in the Allegro 4.4.2 library 20 | (source file "allegro.c"), as well as the "vga_palette" in the DOSBox 21 | 0.74 DOS emulator, which includes VGA card emulation (source file 22 | "int10_modes.cpp"). The only exception is that the very last color 23 | in the palette is full white according to Allegro but full black 24 | according to DOSBox. VGAPAL has the last eight colors as full black, 25 | matching DOSBox. 26 | 27 | Wikipedia references a 28 | ["Default VGA 256-color palette"](https://commons.wikimedia.org/w/index.php?title=File:VGA_palette_with_black_borders.svg&oldid=158578722) 29 | posted by user "Psychonaut" on Wikimedia Commons. Examining the 30 | [source code](https://commons.wikimedia.org/w/index.php?title=User:Psychonaut/ipalette.sh&oldid=8607095) 31 | used to generate the diagram indicates that 8-bit, 256-level colors 32 | were used for the palette instead of the original 6-bit, 64-level 33 | colors. Although the palette posted by Psychonaut appears to have the 34 | same structure as the palette generated by VGAPAL, the upconverted 35 | 8-bit palette generated by VGAPAL does not exactly match the 8-bit RGB 36 | channel values that Psychonaut uses. Unfortunately, Psychonaut does 37 | not specify how the 6-bit RGB palette values were upconverted to 8-bit, 38 | nor is the source of the palette colors specified, so it is difficult 39 | to analyze the discrepancy further. Similar to DOSBox, Psychonaut has 40 | the last color of the palette as full black, which matches VGAPAL. 41 | 42 | The first 16 colors of the generated palette match the colors used in 43 | 16-color VGA modes. To decode these colors, consider the four least 44 | significant bits of the palette index to be IRGB, in order from most 45 | significant to least significant. The RGB bits turn on the relevant 46 | RGB channel while the I bit makes the resulting color brighter. The 47 | only exception to these rules is that what would normally be dark 48 | yellow (I bit OFF, RG bits ON, B bit OFF) is modified slightly to make 49 | it brown instead. 50 | 51 | The next 16 colors of the generated palette are a grayscale gradient 52 | ranging from full black to full white. 53 | 54 | The rest of the palette after the grayscale gradient is occupied by 55 | nine "cycles," each consisting of 24 colors. Each cycle consists of 56 | six "runs" of four colors each. Each run gradually changes one of the 57 | RGB channels from "high" intensity to "low" intensity or from "low" 58 | intensity to "high" intensity, with the definition of "low" and "high" 59 | varying depending on the particular cycle. The pattern is that each 60 | cycle starts at blue high and red and green low. The first run changes 61 | red from low to high. The second run changes blue from high to low. 62 | The third run changes green from low to high. The fourth run changes 63 | red from high to low. The fifth run changes blue from low to high. 64 | And, finally, the sixth run changes green from high to low. At the 65 | end of the sixth run, we're back where we started from with blue high 66 | and red and green low, thereby completing the cycle. 67 | 68 | The effect of the cycle is to run through all the hues in a 69 | hue-saturation-value (HSV) color space. 70 | 71 | The nine cycles differ from each other in their definition of "high" 72 | and "low" (as discussed earlier), as well as in what intermediate 73 | values they use to transition between high and low during runs. These 74 | values are defined so as to vary the saturation and value of each of 75 | the nine cycles. 76 | 77 | The nine cycles are organized into three subgroups, each containing 78 | three cycles. The first subgroup has high defined as full intensity, 79 | yielding high value for the colors in these cycles. The second 80 | subgroup has high defined as moderate intensity, yielding moderate 81 | value for the colors in these cycles. The third subgroup has high 82 | defined as low intensity, yielding low value for the colors in these 83 | cycles. 84 | 85 | Within each subgroup, the first cycle has low defined as zero 86 | intensity, yielding maximum saturation for the colors in the first 87 | cycle of each subgroup. The second cycle has low defined halfway 88 | between zero and high intensity, yielding moderate saturation for the 89 | colors in the second cycle of each subgroup. Finally, the third cycle 90 | has low defined close to high intensity, yielding low saturation for 91 | the colors in the third cycle of each subgroup. 92 | 93 | The 16-color IRGB palette, the 16-color grayscale palette, and the nine 94 | RGB cycles leave eight colors left over at the end of the 256-color 95 | palette. These are simply filled with full black. 96 | 97 | In essence, the default VGA 256-color palette consists of a 16-color 98 | IRGB palette (for backwards compatibility with 16-color modes), 99 | followed by a grayscale palette and RGB cycles designed to cover the 100 | HSV color space. Considering the HSV color space in its usual cone 101 | geometry, the grayscale palette represents the neutral, unsaturated 102 | colors at the center of the cone, while the RGB cycles represent the 103 | rest of the colors, radiating out from the center of the cone. 104 | 105 | 106 | -------------------------------------------------------------------------------- /vgapal.c: -------------------------------------------------------------------------------- 1 | /* 2 | * vgapal.c 3 | * 4 | * Program that constructs the standard VGA palette and outputs it as 5 | * text to standard output. 6 | * 7 | * The text output is formatted as rows of decimal values representing 8 | * unsigned bytes. Each triple of decimal values specifies the red, 9 | * green, and blue value of a palette entry (in that order). Palette 10 | * entries are output in order, all 256 of them. 11 | * 12 | * This program accepts a single command-line argument beyond the 13 | * program name. This single argument must either be "64" or "256" and 14 | * it specifies how many intensity levels each channel has. "64" 15 | * indicates each RGB channel has a range from [0, 63] (matching the 16 | * classic VGA palette), while "256" indicates each RGB channel has a 17 | * range from [0, 255] (matching modern hardware). 18 | * 19 | * The 256-level palette is derived from the 64-level palette by 20 | * shifting each channel value left by two bits and duplicating the two 21 | * most significant bits in the two least significant bits. 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | /* Function prototypes */ 29 | static void addColor(int r, int g, int b); 30 | static void addGrayColor(int v); 31 | static void add16Color(int lo, int melo, int mehi, int hi); 32 | static int addRun( 33 | int start, 34 | int ch, 35 | int lo, 36 | int melo, 37 | int me, 38 | int mehi, 39 | int hi); 40 | static void addCycle(int lo, int melo, int me, int mehi, int hi); 41 | static void buildPalette(void); 42 | static void levelUp(void); 43 | static void printPalette(int levelup); 44 | static void vgapal(int levelup); 45 | 46 | /* The array that will contain the calculated palette, in unsigned byte 47 | triples */ 48 | static unsigned char pal[256 * 3]; 49 | 50 | /* The number of palette entries that have been written to pal */ 51 | static int pal_written = 0; 52 | 53 | /* 54 | * Add another color entry to the palette. 55 | * 56 | * All palette entries added here must use 64-level values. 57 | * 58 | * Parameters: 59 | * 60 | * r - the red channel value 61 | * 62 | * g - the green channel value 63 | * 64 | * b - the blue channel value 65 | */ 66 | static void addColor(int r, int g, int b) { 67 | 68 | int i = 0; 69 | 70 | /* Check ranges */ 71 | if ((r < 0) || (r > 63) || 72 | (g < 0) || (g > 63) || 73 | (b < 0) || (b > 63)) { 74 | abort(); 75 | } 76 | 77 | /* Check that palette isn't full */ 78 | if (pal_written >= 256) { 79 | abort(); 80 | } 81 | 82 | /* Check that pal_written is sane */ 83 | if (pal_written < 0) { 84 | abort(); 85 | } 86 | 87 | /* Calculate starting offset in palette */ 88 | i = pal_written * 3; 89 | 90 | /* Write the color to palette */ 91 | pal[i] = (unsigned char) r; 92 | pal[i + 1] = (unsigned char) g; 93 | pal[i + 2] = (unsigned char) b; 94 | 95 | /* Update pal_written */ 96 | pal_written++; 97 | } 98 | 99 | /* 100 | * Add a grayscale color to the palette. 101 | * 102 | * This calls through to addColor with all channel values equal to 103 | * the provided v. 104 | * 105 | * Parameters: 106 | * 107 | * v - the grayscale value 108 | */ 109 | static void addGrayColor(int v) { 110 | addColor(v, v, v); 111 | } 112 | 113 | /* 114 | * Add the 16 color entries of the standard 16-color palette. 115 | * 116 | * Parameters: 117 | * 118 | * lo - the low intensity value to use 119 | * 120 | * melo - the medium-low intensity value to use 121 | * 122 | * mehi - the medium-high intensity value to use 123 | * 124 | * hi - the high intensity value to use 125 | */ 126 | static void add16Color(int lo, int melo, int mehi, int hi) { 127 | 128 | int r = 0; 129 | int g = 0; 130 | int b = 0; 131 | int i = 0; 132 | int h = 0; 133 | int l = 0; 134 | 135 | /* The passed values must be in 64-level range */ 136 | if ((lo < 0) || (lo > 63) || 137 | (melo < 0) || (melo > 63) || 138 | (mehi < 0) || (mehi > 63) || 139 | (hi < 0) || (hi > 63)) { 140 | abort(); 141 | } 142 | 143 | /* Generate each of the 16 values */ 144 | for(i = 0; i < 16; i++) { 145 | /* Determine whether low-intensity series or high-intensity */ 146 | if ((i & 8) == 8) { 147 | /* Intensity bit set -- define intense range */ 148 | h = hi; 149 | l = melo; 150 | 151 | } else { 152 | /* Intensity bit clear -- define low-intensity range */ 153 | h = mehi; 154 | l = lo; 155 | } 156 | 157 | /* Start by setting each channel to low value */ 158 | r = l; 159 | g = l; 160 | b = l; 161 | 162 | /* Activate channels selected by the appropriate bit */ 163 | if ((i & 4) == 4) { 164 | r = h; 165 | } 166 | if ((i & 2) == 2) { 167 | g = h; 168 | } 169 | if ((i & 1) == 1) { 170 | b = h; 171 | } 172 | 173 | /* As an exceptional case, for index 6 only, change the green 174 | component to medium-low intensity so that we get brown instead 175 | of dark yellow */ 176 | if (i == 6) { 177 | g = melo; 178 | } 179 | 180 | /* Add this color */ 181 | addColor(r, g, b); 182 | } 183 | } 184 | 185 | /* 186 | * Add four colors to the palette corresponding to a "run" within an 187 | * RGB cycle. 188 | * 189 | * start, ch, and the return value are encoded such that only the three 190 | * least significant bits are used. The most significant of these 191 | * corresponds to red, the next to green, and the least significant to 192 | * blue. 193 | * 194 | * Intensity values must be 64-level. 195 | * 196 | * Parameters: 197 | * 198 | * start - high and low starting states for each channel at the start 199 | * of the run 200 | * 201 | * ch - the channel to change from high to low or low to high (only 202 | * one bit may be set) 203 | * 204 | * lo - the low intensity value 205 | * 206 | * melo - the medium-low intensity value 207 | * 208 | * me - the medium intensity value 209 | * 210 | * mehi - the medium-high intensity value 211 | * 212 | * hi - the high intensity value 213 | * 214 | * Return: 215 | * 216 | * the high and low starting states for each channel at the start of 217 | * the run after this one 218 | */ 219 | static int addRun( 220 | int start, 221 | int ch, 222 | int lo, 223 | int melo, 224 | int me, 225 | int mehi, 226 | int hi) { 227 | 228 | int r = 0; 229 | int g = 0; 230 | int b = 0; 231 | int i = 0; 232 | int up = 0; 233 | int v = 0; 234 | 235 | /* Check parameters */ 236 | if ((start < 0) || (start > 7)) { 237 | abort(); 238 | } 239 | if ((ch != 1) && (ch != 2) && (ch != 4)) { 240 | abort(); 241 | } 242 | if ((lo < 0) || (lo > 63) || 243 | (melo < 0) || (melo > 63) || 244 | (me < 0) || (me > 63) || 245 | (mehi < 0) || (mehi > 63) || 246 | (hi < 0) || (hi > 63)) { 247 | abort(); 248 | } 249 | 250 | /* Get the starting RGB color and add it */ 251 | r = lo; 252 | g = lo; 253 | b = lo; 254 | 255 | if ((start & 4) == 4) { 256 | r = hi; 257 | } 258 | if ((start & 2) == 2) { 259 | g = hi; 260 | } 261 | if ((start & 1) == 1) { 262 | b = hi; 263 | } 264 | 265 | addColor(r, g, b); 266 | 267 | /* If selected channel starts high, we're going down; else, we're 268 | going up */ 269 | if ((start & ch) == ch) { 270 | up = 0; 271 | } else { 272 | up = 1; 273 | } 274 | 275 | /* Add remaining three colors of the run */ 276 | for(i = 0; i < 3; i++) { 277 | /* Value depends if we're going up or down */ 278 | if (up) { 279 | /* Going up */ 280 | if (i == 0) { 281 | v = melo; 282 | } else if (i == 1) { 283 | v = me; 284 | } else { 285 | v = mehi; 286 | } 287 | } else { 288 | /* Going down */ 289 | if (i == 0) { 290 | v = mehi; 291 | } else if (i == 1) { 292 | v = me; 293 | } else { 294 | v = melo; 295 | } 296 | } 297 | 298 | /* Adjust the proper channel */ 299 | if (ch == 4) { 300 | r = v; 301 | } else if (ch == 2) { 302 | g = v; 303 | } else { 304 | b = v; 305 | } 306 | 307 | /* Add the color */ 308 | addColor(r, g, b); 309 | } 310 | 311 | /* The next run starts at the starting position of this run, with the 312 | channel we just handled flipped */ 313 | return (start ^ ch); 314 | } 315 | 316 | /* 317 | * Add a 24-color RGB cycle to the palette. 318 | * 319 | * A cycle consists of six 4-color runs, each of which transitions from 320 | * one hue to another until arriving back at starting position. 321 | * 322 | * Intensities must be provided in 64-level scale. 323 | * 324 | * Parameters: 325 | * 326 | * lo - low intensity value 327 | * 328 | * melo - medium-low intensity value 329 | * 330 | * me - medium intensity value 331 | * 332 | * mehi - medium-high intensity value 333 | * 334 | * hi - high intensity value 335 | */ 336 | static void addCycle(int lo, int melo, int me, int mehi, int hi) { 337 | 338 | int hue = 0; 339 | 340 | /* Check parameters */ 341 | if ((lo < 0) || (lo > 63) || 342 | (melo < 0) || (melo > 63) || 343 | (me < 0) || (me > 63) || 344 | (mehi < 0) || (mehi > 63) || 345 | (hi < 0) || (hi > 63)) { 346 | abort(); 347 | } 348 | 349 | /* We start out at blue */ 350 | hue = 1; 351 | 352 | /* Add each run, updating the hue each time */ 353 | hue = addRun(hue, 4, lo, melo, me, mehi, hi); 354 | hue = addRun(hue, 1, lo, melo, me, mehi, hi); 355 | hue = addRun(hue, 2, lo, melo, me, mehi, hi); 356 | 357 | hue = addRun(hue, 4, lo, melo, me, mehi, hi); 358 | hue = addRun(hue, 1, lo, melo, me, mehi, hi); 359 | hue = addRun(hue, 2, lo, melo, me, mehi, hi); 360 | } 361 | 362 | /* 363 | * Write all 256 colors to the palette using addColor. 364 | * 365 | * The palette is always written here as 64-level. 366 | */ 367 | static void buildPalette(void) { 368 | int x = 0; 369 | 370 | /* Add the 16-color palette first */ 371 | add16Color(0, 21, 42, 63); 372 | 373 | /* Next we have 16 shades of gray */ 374 | addGrayColor( 0); 375 | addGrayColor( 5); 376 | addGrayColor( 8); 377 | addGrayColor(11); 378 | addGrayColor(14); 379 | addGrayColor(17); 380 | addGrayColor(20); 381 | addGrayColor(24); 382 | addGrayColor(28); 383 | addGrayColor(32); 384 | addGrayColor(36); 385 | addGrayColor(40); 386 | addGrayColor(45); 387 | addGrayColor(50); 388 | addGrayColor(56); 389 | addGrayColor(63); 390 | 391 | /* Now come the nine RGB cycles, organized in three groups of three 392 | cycles -- the groups represent high value, medium value, and low 393 | value, and the cycles within the groups represent high saturation, 394 | medium saturation, low saturation */ 395 | addCycle( 0, 16, 31, 47, 63); 396 | addCycle(31, 39, 47, 55, 63); 397 | addCycle(45, 49, 54, 58, 63); 398 | 399 | addCycle( 0, 7, 14, 21, 28); 400 | addCycle(14, 17, 21, 24, 28); 401 | addCycle(20, 22, 24, 26, 28); 402 | 403 | addCycle( 0, 4, 8, 12, 16); 404 | addCycle( 8, 10, 12, 14, 16); 405 | addCycle(11, 12, 13, 15, 16); 406 | 407 | /* Fill the last eight palette entries with full black */ 408 | addGrayColor(0); 409 | addGrayColor(0); 410 | addGrayColor(0); 411 | addGrayColor(0); 412 | 413 | addGrayColor(0); 414 | addGrayColor(0); 415 | addGrayColor(0); 416 | addGrayColor(0); 417 | } 418 | 419 | /* 420 | * Convert the palette from 64-level to 256-level. 421 | * 422 | * This may only be called once. All 256 colors of the palette must 423 | * already have been added. 424 | */ 425 | static void levelUp(void) { 426 | static int first_call = 1; 427 | 428 | int i = 0; 429 | int v = 0; 430 | 431 | /* Can only call once */ 432 | if (first_call) { 433 | first_call = 0; 434 | } else { 435 | abort(); 436 | } 437 | 438 | /* Palette must be full */ 439 | if (pal_written != 256) { 440 | abort(); 441 | } 442 | 443 | /* Convert each individual component from 64-level to 256-level */ 444 | for(i = 0; i < (256 * 3); i++) { 445 | /* Get component value */ 446 | v = pal[i]; 447 | 448 | /* Verify range */ 449 | if (v > 63) { 450 | abort(); 451 | } 452 | 453 | /* First, shift value two bits left */ 454 | v = (v << 2); 455 | 456 | /* Second, duplicate two most significant bits of byte in two least 457 | significant bits */ 458 | v = v | (v >> 6); 459 | 460 | /* Write converted value back to palette */ 461 | pal[i] = (unsigned char) v; 462 | } 463 | } 464 | 465 | /* 466 | * Print the contents of the palette. 467 | * 468 | * All 256 colors must already have been added to the palette. The 469 | * palette must *not* have already been upconverted from 64-level to 470 | * 256-level; this procedure will do that if requested. 471 | * 472 | * Parameters: 473 | * 474 | * levelup - non-zero if the palette should be upconverted to 256 475 | * levels before being printed, zero to leave it at 64 levels 476 | */ 477 | static void printPalette(int levelup) { 478 | 479 | int i = 0; 480 | 481 | /* Palette must be full */ 482 | if (pal_written != 256) { 483 | abort(); 484 | } 485 | 486 | /* Upconvert the palette if requested */ 487 | if (levelup) { 488 | levelUp(); 489 | } 490 | 491 | /* Write each component */ 492 | for(i = 0; i < (256 * 3); i++) { 493 | 494 | /* Figure out if we need to prefix a separator */ 495 | if (i == 0) { 496 | /* First component -- no separator */ 497 | 498 | } else if ((i % 12) == 0) { 499 | /* Not first component but multiple of 12 (every four colors), so 500 | add a line break */ 501 | printf("\n"); 502 | 503 | } else if ((i % 3) == 0) { 504 | /* Not a multiple of 12 but a multiple of three (each color), so 505 | add double space separator */ 506 | printf(" "); 507 | 508 | } else { 509 | /* Not a multiple of three, so just add a single space */ 510 | printf(" "); 511 | } 512 | 513 | /* Output component value, aligned to 3-digit if 256-level or 514 | 2-digit if 64-level */ 515 | if (levelup) { 516 | printf("%3d", (int) pal[i]); 517 | } else { 518 | printf("%2d", (int) pal[i]); 519 | } 520 | 521 | /* If not the last component, suffix a comma */ 522 | if (i < (256 * 3) - 1) { 523 | printf(","); 524 | } 525 | } 526 | 527 | /* Add a line break at the very end */ 528 | printf("\n"); 529 | } 530 | 531 | /* 532 | * Program procedure. 533 | * 534 | * Parameters: 535 | * 536 | * levelup - non-zero if output should be converted to 256-level, 537 | * zero for output in 64-level 538 | */ 539 | static void vgapal(int levelup) { 540 | buildPalette(); 541 | printPalette(levelup); 542 | } 543 | 544 | /* 545 | * Main procedure. 546 | * 547 | * Parameters: 548 | * 549 | * argc - number of command-line arguments (including program name) 550 | * 551 | * argv - array of pointers to null-terminated ASCII arguments 552 | * 553 | * Return: 554 | * 555 | * zero if successful, one if error 556 | */ 557 | int main(int argc, char *argv[]) { 558 | 559 | int status = 1; 560 | int levelup = 0; 561 | 562 | /* Number of arguments must be at least one and argument array must 563 | not be NULL */ 564 | if ((argc < 1) || (argv == NULL)) { 565 | abort(); 566 | } 567 | 568 | /* If no additional arguments, display help screen and fail */ 569 | if (status && (argc <= 1)) { 570 | fprintf(stderr, "%s [levels]\n\n", argv[0]); 571 | fprintf(stderr, "levels - either 64 or 256, indicating maximum\n"); 572 | fprintf(stderr, "channel intensity value\n\n"); 573 | status = 0; 574 | } 575 | 576 | /* If too many arguments, fail */ 577 | if (status && (argc > 2)) { 578 | fprintf(stderr, "%s: Too many arguments!\n", argv[0]); 579 | status = 0; 580 | } 581 | 582 | /* Parse parameter, setting levelup flag if we need to convert up to 583 | 256-level output */ 584 | if (status) { 585 | if (argv[1] == NULL) { 586 | abort(); 587 | } 588 | 589 | if (strcmp(argv[1], "64") == 0) { 590 | /* 64-level; no upconversion required */ 591 | levelup = 0; 592 | } else if (strcmp(argv[1], "256") == 0) { 593 | /* 256-level; upconversion required */ 594 | levelup = 1; 595 | } else { 596 | /* Unrecognized value */ 597 | fprintf(stderr, "%s: Only 64 and 256 supported for levels.\n", 598 | argv[0]); 599 | status = 0; 600 | } 601 | } 602 | 603 | /* Call through to main program, passing flag */ 604 | if (status) { 605 | vgapal(levelup); 606 | } 607 | 608 | /* Invert status for return */ 609 | if (status) { 610 | status = 0; 611 | } else { 612 | status = 1; 613 | } 614 | 615 | /* Return inverted status */ 616 | return status; 617 | } 618 | --------------------------------------------------------------------------------