|
|
1.1 ! root 1: /* mdraw.c - display Mandelbrot set on EGA ! 2: * R. A. Garmoe 86/12/15 ! 3: */ ! 4: ! 5: ! 6: ! 7: /** Mdraw displays the elements of the Mandelbrot set ! 8: * ! 9: * z = z**2 + c ! 10: * ! 11: * where z and c are in the complex plane and z = 0 + 0i for the first ! 12: * iteration. The elements of the set are displayed in black and ! 13: * elements not in the set are displayed in color. The data to be ! 14: * displayed is computed by the program mandel. ! 15: */ ! 16: ! 17: ! 18: /** Call ! 19: * ! 20: * mdraw file file ... ! 21: * ! 22: * where ! 23: * file a .cnt file created by the computation program mandel ! 24: * ! 25: * All of the files are read and displayed in order. After all of ! 26: * the images are displayed, keystrokes have the following meaning. ! 27: * e edit palette registers ! 28: * up/down arrow - select register ! 29: * right/left arrow - select color ! 30: * i reinitialize palette registers ! 31: * n advance to next display ! 32: * p backup to previous display ! 33: * q cleanup and exit ! 34: * r decrement palette register ripple ! 35: * R increment palette register ripple ! 36: * z continous forward zoom through images ! 37: * Z continous backward zoom through images ! 38: * ! 39: * All other characters are ignored. ! 40: */ ! 41: ! 42: ! 43: ! 44: ! 45: /* ! 46: * The .cnt file has the format ! 47: * int number of points along the real axis ! 48: * int number of points along the imaginary axis ! 49: * int maximum iteration point for each point ! 50: * double real coordinate of upper left ! 51: * double imaginary coordinate of upper left ! 52: * double real coordinate of lower right ! 53: * double imaginary coordinate lower rightft ! 54: * double increment between points on real axis ! 55: * double increment between points on imaginary axis ! 56: * long (loop + 1) counters for histogram values ! 57: * ! 58: * The remainder of the file is the run length encoded scan ! 59: * lines encoded as: ! 60: * int number of words in scan line encoded as: ! 61: * +int actual count value for pixel ! 62: * -int int The first value is the run length and ! 63: * second value is the run value ! 64: */ ! 65: ! 66: ! 67: ! 68: #include <stdio.h> ! 69: #include <subcalls.h> ! 70: #include <doscalls.h> ! 71: #include <dos.h> ! 72: #include "mdraw.h" ! 73: ! 74: /* The routines that are in the IOPL segment must be declared ! 75: * as pascal routines. When the IOPL routine is called through ! 76: * the intersegment call gate, the parameters are copied from the ! 77: * ring 3 user's stack to the ring 2 IOPL stack. The parameters ! 78: * must be popped from the IOPL stack (and the ring 3 stack) by the ! 79: * ret n instruction of the IOPL routine. Otherwise, the ring 2 ! 80: * stack is left in an invalid state. For more information, refer ! 81: * to the 80286 Programmer's Manual for ! 82: * intersegment calls ! 83: * parameter passing through call gates ! 84: * CALLs to and RETurns from inner protection rings ! 85: * ! 86: * Note also that the number of words of passed parameters defined in ! 87: * each of these functions must exactly match the word counts defined ! 88: * in the EXPORTS statements in the mdraw.def linker definitions file. ! 89: */ ! 90: ! 91: extern void far pascal SetDVideo (); ! 92: extern void far pascal SetEVideo (); ! 93: extern void far pascal SetScanClear (); ! 94: extern void far pascal SetScan (int, int, char *); ! 95: extern void far pascal SetScanSave (unsigned far *); ! 96: extern void far pascal SetScanSFont (unsigned); ! 97: extern void far pascal SetScanRFont (unsigned); ! 98: extern void far pascal SetScanRestore (unsigned far *); ! 99: extern void far pascal SetCursor (char far *); ! 100: ! 101: ! 102: void far mode_wait (void); /* starting address for a thread */ ! 103: void far redraw_wait (void); /* starting address for another thread */ ! 104: ! 105: ! 106: ! 107: /* Structures for VIO calls */ ! 108: ! 109: struct ConfigData config; /* Display configuration data */ ! 110: struct ModeData mode; /* Display mode data */ ! 111: struct ModeData grmode; /* graphics display mode data */ ! 112: struct PhysBufData physbuf; /* Physical buffer data */ ! 113: struct CursorData cursor; /* Cursor data structure */ ! 114: struct KeyData key; /* Keystroke data */ ! 115: struct VIOSTATE vstate; /* Set vio state */ ! 116: ! 117: ! 118: ! 119: ! 120: char pmand[60] = "mandel.cnt"; ! 121: FILE *fmand; ! 122: ! 123: char chvalid = FALSE; /* key valid if true */ ! 124: char cinit[15] = {WHITE, BLUE, GREEN, CYAN, RED, MAGENTA, BROWN, IWHITE, ! 125: DGRAY, LBLUE, LGREEN, LCYAN, LRED, LMAGENTA, YELLOW}; ! 126: char firstread = FALSE; /* first character read from keyboard if true */ ! 127: char flip = FALSE; /* flip display pages if true */ ! 128: char graphics = FALSE; /* display is in graphics mode if true */ ! 129: char mapped[MAXREAL]; /* character array holding mapped interation counters */ ! 130: char initpal[16] = { ! 131: 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, ! 132: 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F ! 133: }; ! 134: char palette[16] = { ! 135: 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, ! 136: 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F ! 137: }; ! 138: ! 139: char *screenbuf; /* pointer to buffer to hold text screen */ ! 140: ! 141: int *bp; /* pointer to next iteration counter in buf */ ! 142: int buf[BUFFER]; /* run length encoded iteration counters */ ! 143: int count = 0; /* number of integers remaining in buf */ ! 144: ! 145: long delay = 0; /* ripple delay in milliseconds */ ! 146: long drawsem = 0; /* RAM semaphore to control drawing */ ! 147: long hist[MAXLOOP + 1] = {0}; /* histogram counters */ ! 148: ! 149: struct image timage = {0}; /* local image descriptor structure */ ! 150: struct ilist *head = NULL; /* pointer to head of ilist */ ! 151: struct ilist *curr = NULL; /* pointer to current ilist */ ! 152: struct ilist *tail = NULL; /* pointer to tail of ilist */ ! 153: ! 154: unsigned curcol; /* cursor column position */ ! 155: unsigned currow; /* cursor row position */ ! 156: unsigned descsel; /* selector for image structure */ ! 157: unsigned fontsel; /* selectors for font saves */ ! 158: unsigned dpoffset = 0; /* display page offset 0x0000 or 0x8000 */ ! 159: unsigned *psel; /* display memory selector */ ! 160: unsigned screenlen; /* length of screen buffer */ ! 161: ! 162: main (argc, argv) ! 163: int argc; ! 164: char **argv; ! 165: { ! 166: int c; ! 167: int i; ! 168: int temp; ! 169: int pal; ! 170: unsigned char *stack1, /* stack for mode_wait thread */ ! 171: *stack2; /* stack for redraw_wait thread */ ! 172: unsigned ThreadID; ! 173: ! 174: /* Validate the display configuration. It must be an EGA on an ! 175: * EGA adapter with at least 128k of memory. ! 176: */ ! 177: ! 178: config.length = 10; ! 179: if ((temp = VIOGETCONFIG (0, (struct ConfigData far *)&config, 0)) != 0) { ! 180: printf ("Unable to get display configuration data - %d\n", temp); ! 181: exit (1); ! 182: } ! 183: if ((config.adapter_type != 2) || (config.display_type != 2) || ! 184: config.memory_size < 0x20000) { ! 185: printf ("Display is not EGA on 128k EGA adapter %d %d %ld\n", ! 186: config.adapter_type, config.display_type, config.memory_size); ! 187: exit (1); ! 188: } ! 189: ! 190: if (config.memory_size == 0x40000) ! 191: flip = TRUE; ! 192: ! 193: /* Save information about the current display mode. This includes ! 194: * the current mode as known by VIO, the cursor type data, the ! 195: * current cursor position and the text screen data. ! 196: */ ! 197: ! 198: mode.length = sizeof (struct ModeData); ! 199: if ((temp = VIOGETMODE ((struct ModeData far *)&mode, 0)) != 0) { ! 200: printf ("Unable to get display mode data - %d\n", temp); ! 201: exit (1); ! 202: } ! 203: if (VIOGETCURTYPE ((struct CursorData *)&cursor, 0) != 0) { ! 204: printf ("Unable to get current cursor data\n"); ! 205: exit (1); ! 206: } ! 207: if (VIOGETCURPOS ((unsigned far *)&currow, (unsigned far *)&curcol, 0) != 0) { ! 208: printf ("Unable to get current cursor position\n"); ! 209: exit (1); ! 210: } ! 211: ! 212: /* Allocate buffer to hold text screen data. Note that the buffer ! 213: * size is doubled because of the attribute bytes. ! 214: */ ! 215: ! 216: screenlen = mode.col * mode.row * 2; ! 217: if ((screenbuf = (char *)malloc (screenlen)) == NULL) { ! 218: printf ("Unable to allocate memory for text screen buffer\n"); ! 219: exit (1); ! 220: } ! 221: if (VIOREADCELLSTR ((char far *)screenbuf, (unsigned far *)&screenlen, ! 222: 0, 0, 0) != 0) { ! 223: printf ("Unable to read text screen data\n"); ! 224: exit (1); ! 225: } ! 226: ! 227: /* Obtain selectors to the display memory */ ! 228: ! 229: physbuf.buf_start = 0xa0000; ! 230: physbuf.buf_length = 0x20000; ! 231: if ((temp = VIOGETPHYSBUF ((struct PhysBufData far *)&physbuf, 0)) != 0) { ! 232: printf ("Unable to get physical buffer mapping - %d\n", temp); ! 233: exit (1); ! 234: } ! 235: if (DOSALLOCSEG (0,(unsigned far *)&fontsel, 0) != 0) { ! 236: printf ("Unable to allocate text font save segment\n"); ! 237: exit (1); ! 238: } ! 239: /* Allocate memory for separate thread execution */ ! 240: ! 241: stack1 = (unsigned char *)malloc (STACKSIZE); ! 242: stack2 = (unsigned char *)malloc (STACKSIZE); ! 243: if (!stack1 || !stack2) { ! 244: printf ("Out of memory\n"); ! 245: exit (1); ! 246: } ! 247: stack1 += STACKSIZE; ! 248: stack2 += STACKSIZE; ! 249: ! 250: /* create thread to execute the mode wait */ ! 251: ! 252: DOSCREATETHREAD (mode_wait, &ThreadID, stack1); ! 253: ! 254: /* create thread that will execute the redraw_wait () */ ! 255: ! 256: DOSCREATETHREAD (redraw_wait, &ThreadID, stack2); ! 257: ! 258: ! 259: /* Pass pointer to the selectors for display memory and the ! 260: * selector to the font save segment to the ring 2 IOPL code. ! 261: */ ! 262: ! 263: psel = physbuf.selectors; ! 264: ! 265: /* Save the font tables */ ! 266: ! 267: SetScanSFont (fontsel); ! 268: ! 269: /* Set the EGA to 640 x 350 graphics mode */ ! 270: ! 271: grmode = mode; ! 272: grmode.type = grmode.type | 0x02; ! 273: grmode.hres = 640; ! 274: grmode.vres = 350; ! 275: VIOSETMODE ((struct ModeData far *)&grmode, 0); ! 276: DOSSEMREQUEST ((unsigned long)(long far *)&drawsem, (long)-1); ! 277: setpalette (palette); ! 278: DOSSEMCLEAR ((unsigned long)(long far *)&drawsem); ! 279: ! 280: /* Set the file name if specified and open the file for reading */ ! 281: ! 282: argc--; ! 283: argv++; ! 284: graphics = TRUE; ! 285: printf ("Clearing screen\n"); ! 286: SetScanClear (); ! 287: printf ("Screen cleared\n"); ! 288: while (argc > 0) { ! 289: /* set file name */ ! 290: strcpy (pmand, *argv); ! 291: strcat (pmand, ".cnt"); ! 292: if ((fmand = fopen (pmand, "rb")) == NULL) { ! 293: cleandisplay (); ! 294: printf ("Unable to open count file %s\n", pmand); ! 295: exit (3); ! 296: } ! 297: readimage (); ! 298: fclose (fmand); ! 299: argc--; ! 300: argv++; ! 301: } ! 302: ! 303: /* Wait for keyboard input to switch display or terminate. This ! 304: * thread must delay between checks for keyboard input. Otherwise, ! 305: * the code will execute a CPU bound loop and all other threads ! 306: * and processes will execute at a reduced rate. ! 307: */ ! 308: ! 309: while (TRUE) { ! 310: if (nextchar (&c, 1)) { ! 311: switch (c) { ! 312: case 'e': ! 313: /* edit palette registers */ ! 314: paledit (); ! 315: break; ! 316: ! 317: case 'i': ! 318: /* reinitialize palette registers */ ! 319: for (i = 0; i < 16; i++) ! 320: palette[i] = initpal[i]; ! 321: DOSSEMREQUEST ((unsigned long)(long far *)&drawsem, (long)-1); ! 322: setpalette (palette); ! 323: DOSSEMCLEAR ((unsigned long)(long far *)&drawsem); ! 324: break; ! 325: ! 326: case 'n': ! 327: /* advance to next display */ ! 328: nextimage (); ! 329: break; ! 330: ! 331: case 'p': ! 332: /* backup to previous display */ ! 333: previmage (); ! 334: break; ! 335: ! 336: case 'q': ! 337: /* cleanup and exit */ ! 338: cleandisplay (); ! 339: exit (); ! 340: ! 341: case 'r': ! 342: /* decrement palette register ripple */ ! 343: delay += SCANTIME; ! 344: break; ! 345: ! 346: case 'R': ! 347: /* increment palette register ripple */ ! 348: delay -= SCANTIME; ! 349: break; ! 350: ! 351: case 'z': ! 352: /* continous forward zoom through images */ ! 353: while (!nextchar (&c, 1)) ! 354: nextimage (); ! 355: ungetchar (); ! 356: break; ! 357: ! 358: case 'Z': ! 359: /* continous backward zoom through images */ ! 360: while (!nextchar (&c, 1)) ! 361: previmage (); ! 362: ungetchar (); ! 363: break; ! 364: ! 365: default: ! 366: /* ignore character */ ! 367: break; ! 368: } ! 369: } ! 370: ! 371: /* delay to prevent CPU bound loop */ ! 372: ! 373: if (delay == 0) ! 374: DOSSLEEP ((long)100); ! 375: else if (delay > 0) { ! 376: ripple (RIPPLE_UP); ! 377: DOSSLEEP (delay); ! 378: } ! 379: else { ! 380: ripple (RIPPLE_DN); ! 381: DOSSLEEP ((long)(-delay)); ! 382: } ! 383: } ! 384: } ! 385: ! 386: ! 387: ! 388: ! 389: /** mdisp - display Mandelbrot set ! 390: * ! 391: * mdisp (im); ! 392: * ! 393: */ ! 394: ! 395: ! 396: ! 397: mdisp (im) ! 398: struct image far *im; ! 399: { ! 400: int i; ! 401: int ni; /* scan row counter */ ! 402: int temp; ! 403: int len; ! 404: char *pmapped; ! 405: ! 406: VIOSCRLOCK (1, (char far *)&temp, 0); ! 407: DOSSEMREQUEST ((unsigned long)(long far *)&drawsem, (long)-1); ! 408: SetScanClear (); ! 409: DOSSEMCLEAR ((unsigned long)(long far *)&drawsem); ! 410: ! 411: for (ni = 0; ni < im->lni; ni++) { ! 412: pmapped = mapped; ! 413: if (!nextvalue (&len)) ! 414: break; ! 415: while ((--len >= 0) && (pmapped - mapped < im->lnr) && nextvalue (&i)) { ! 416: if (i >= 0) ! 417: *pmapped++ = im->cmap[i]; ! 418: else { ! 419: if (!nextvalue (&temp)) ! 420: break; ! 421: len--; ! 422: temp = im->cmap[temp]; ! 423: for (; (i < 0) && (pmapped - mapped < im->lnr); i++) ! 424: *pmapped++ = temp; ! 425: } ! 426: } ! 427: ! 428: /* The scan line drawing is locked with a RAM semaphore so ! 429: * the redraw-wait routine can save and restore the screen ! 430: */ ! 431: ! 432: DOSSEMREQUEST ((unsigned long)(long far *)&drawsem, (long)-1); ! 433: SetScan (ni, im->lnr, mapped); ! 434: DOSSEMCLEAR ((unsigned long)(long far *)&drawsem); ! 435: } ! 436: ! 437: /* Save screen image and unlock the screen */ ! 438: ! 439: DOSSEMREQUEST ((unsigned long)(long far *)&drawsem, (long)-1); ! 440: SetScanSave (curr->desc->savesel); ! 441: DOSSEMCLEAR ((unsigned long)(long far *)&drawsem); ! 442: ! 443: VIOSCRUNLOCK (0); ! 444: } ! 445: ! 446: ! 447: ! 448: ! 449: /** nextvalue - return next value from file ! 450: * ! 451: * flag = nextvalue (ptr); ! 452: * ! 453: * Entry ptr = pointer to integer to receive value ! 454: * Exit *ptr = next value from file ! 455: * Return TRUE if next value returned ! 456: * FALSE if end of file ! 457: */ ! 458: ! 459: ! 460: int nextvalue (p) ! 461: int *p; ! 462: { ! 463: if (count == 0) { ! 464: count = fread ((char *)buf, sizeof (int), BUFFER, fmand); ! 465: bp = buf; ! 466: } ! 467: if (count == EOF) ! 468: return (FALSE); ! 469: *p = *bp++; ! 470: count--; ! 471: return (TRUE); ! 472: } ! 473: ! 474: ! 475: ! 476: ! 477: /** mode_wait - wait for mode reset request ! 478: * ! 479: * This routine is executed by another thread that is started ! 480: * by the main routine. ! 481: * ! 482: * This routine calls VIOmode_wait requesting to be notified ! 483: * after the completion of an application or hard error popup. ! 484: * On such a notification, it puts the screen in the desired ! 485: * graphics mode. ! 486: */ ! 487: ! 488: void mode_wait () ! 489: { ! 490: unsigned NotifyType; ! 491: ! 492: while (TRUE) { ! 493: /* wait for notification to restore mode */ ! 494: VIOMODEWAIT (0, &NotifyType, 0); ! 495: if (NotifyType == 0 && graphics) ! 496: DOSSEMREQUEST ((unsigned long)(long far *)&drawsem, (long)-1); ! 497: VIOSETMODE ((struct ModeData far *)&grmode, 0); ! 498: SetScanClear (); ! 499: DOSSEMCLEAR ((unsigned long)(long far *)&drawsem); ! 500: } ! 501: } ! 502: ! 503: ! 504: ! 505: ! 506: /** redraw_wait - wait for mode reset request ! 507: * ! 508: * This routine is executed by another thread that is started ! 509: * by the main routine. ! 510: * ! 511: * This routine calls VioSavRedrawWait requesting to be notified ! 512: * for both save and redraw. On save notification, it copies the ! 513: * EGA adapter memory to allocated memory segments. On redraw ! 514: * notification, it puts the screen in the desired graphics mode ! 515: * and then redraws the Mandelbrot set. ! 516: */ ! 517: ! 518: ! 519: void redraw_wait () ! 520: { ! 521: unsigned NotifyType; ! 522: ! 523: while (TRUE) { ! 524: VIOSAVREDRAWWAIT (0, &NotifyType, 0); ! 525: if (graphics) { ! 526: if (NotifyType == 0) { ! 527: /* save graphics screen */ ! 528: DOSSEMREQUEST ((unsigned long)(long far *)&drawsem, (long)-1); ! 529: SetScanSave (curr->desc->savesel); ! 530: SetScanClear (); ! 531: continue; ! 532: } ! 533: else if (NotifyType == 1) { ! 534: /* restore graphics screen */ ! 535: dpoffset = 0; ! 536: VIOSETMODE ((struct ModeData far *)&grmode, 0); ! 537: SetScanClear (); ! 538: SetDVideo (); ! 539: SetScanRestore (curr->desc->savesel); ! 540: SetEVideo (); ! 541: DOSSEMCLEAR ((unsigned long)(long far *)&drawsem); ! 542: } ! 543: } ! 544: } ! 545: } ! 546: ! 547: ! 548: ! 549: ! 550: /** readimage - read and display next image ! 551: * ! 552: * readimage (); ! 553: * ! 554: */ ! 555: ! 556: ! 557: readimage () ! 558: { ! 559: int i; ! 560: struct ilist *tlist; ! 561: int nr; ! 562: ! 563: /* Allocate memory for image structure and link to chain of images */ ! 564: ! 565: if ((tlist = (struct ilist *)malloc (sizeof (struct ilist))) == NULL) { ! 566: cleandisplay (); ! 567: printf ("Unable to allocate memory for ilist structure\n"); ! 568: exit (1); ! 569: } ! 570: if (DOSALLOCSEG (sizeof (struct image),(unsigned far *)&descsel, 0) != 0) { ! 571: cleandisplay (); ! 572: printf ("Unable to allocate image descriptor segment of %d bytes\n", sizeof (struct image)); ! 573: exit (1); ! 574: } ! 575: ! 576: FP_SEG (tlist->desc) = descsel; ! 577: FP_OFF (tlist->desc) = 0; ! 578: ! 579: /* Read description of the computed Mandelbrot set from the file ! 580: * and perform simple validation checks. Limit the display rows and ! 581: * columns to the display maximums. ! 582: */ ! 583: ! 584: if (fread ((char *)&timage.nreal, sizeof (int), 1, fmand) != 1) { ! 585: cleandisplay (); ! 586: printf ("Error reading maximum number of reals %d\n", timage.nreal); ! 587: exit (2); ! 588: } ! 589: timage.lnr = (timage.nreal > 640)? 640: timage.nreal; ! 590: if (fread ((char *)&timage.nimag, sizeof (int), 1, fmand) != 1) { ! 591: cleandisplay (); ! 592: printf ("Error reading maximum number of imaginaries %d\n", timage.nimag); ! 593: exit (2); ! 594: } ! 595: timage.lni = (timage.nimag > 350)? 350: timage.nimag; ! 596: if (fread ((char *)&timage.mloop, sizeof (int), 1, fmand) != 1) { ! 597: cleandisplay (); ! 598: printf ("Error reading maximum loop count %d\n", timage.mloop); ! 599: exit (2); ! 600: } ! 601: if (fread ((char *)&timage.ul, sizeof (timage.ul), 1, fmand) != 1) { ! 602: cleandisplay (); ! 603: printf ("Error reading upper left coordinates\n"); ! 604: exit (2); ! 605: } ! 606: if (fread ((char *)&timage.lr, sizeof (timage.lr), 1, fmand) != 1) { ! 607: cleandisplay (); ! 608: printf ("Error reading lower right coordinates\n"); ! 609: exit (2); ! 610: } ! 611: ! 612: if (fread ((char *)&timage.rinc, sizeof (timage.rinc), 1, fmand) != 1) { ! 613: cleandisplay (); ! 614: printf ("Error reading real increment\n"); ! 615: exit (2); ! 616: } ! 617: if (fread ((char *)&timage.iinc, sizeof (timage.iinc), 1, fmand) != 1) { ! 618: cleandisplay (); ! 619: printf ("Error reading imaginary increment\n"); ! 620: exit (2); ! 621: } ! 622: if (fread ((char *)&timage.aspect, sizeof (timage.aspect), 1, fmand) != 1) { ! 623: cleandisplay (); ! 624: printf ("Error reading aspect ratio\n"); ! 625: exit (2); ! 626: } ! 627: if (fread ((char *)timage.hist, sizeof (long), timage.mloop + 1, fmand) != timage.mloop + 1) { ! 628: cleandisplay (); ! 629: printf ("Error reading histogram\n"); ! 630: exit (2); ! 631: } ! 632: ! 633: /* Assign colors to each iteration count. Black is reserved for ! 634: * points within the Mandelbrot set. ! 635: */ ! 636: ! 637: for (nr = 0; nr < timage.mloop; nr++) { ! 638: timage.cmap[nr] = (nr % 15) + 1; ! 639: } ! 640: timage.cmap[timage.mloop] = 0; ! 641: ! 642: /* Allocate memory for segments to save graphics screen and ! 643: * EGA font tables. ! 644: */ ! 645: ! 646: for ( i = 0; i < 2; i++) { ! 647: if (DOSALLOCSEG (56020, (unsigned far *)&timage.savesel[i], 0) != 0) { ! 648: cleandisplay (); ! 649: printf ("Unable to allocate screen save segments\n"); ! 650: exit (1); ! 651: } ! 652: } ! 653: ! 654: /* Link image to chain of images */ ! 655: ! 656: DOSSEMREQUEST ((unsigned long)(long far *)&drawsem, (long)-1); ! 657: /* copy structure to far segment */ ! 658: *(tlist->desc) = timage; ! 659: tlist->next = NULL; ! 660: tlist->prev = tail; ! 661: if (head == NULL) ! 662: head = tlist; ! 663: else ! 664: tail->next = tlist; ! 665: tail = tlist; ! 666: curr = tlist; ! 667: ! 668: DOSSEMCLEAR ((unsigned long)(long far *)&drawsem); ! 669: ! 670: /* Lock the screen, set the display to graphics mode ! 671: * and draw the Mandelbrot set ! 672: */ ! 673: ! 674: mdisp (curr->desc); ! 675: } ! 676: ! 677: ! 678: ! 679: ! 680: /** ! 681: * ! 682: * ! 683: */ ! 684: ! 685: cleandisplay () ! 686: { ! 687: /* cancel mode wait and redraw wait threads */ ! 688: ! 689: VIOMODEUNDO (GIVEUPOWNER, KILLTHREAD, RESERVED); ! 690: VIOSAVREDRAWUNDO (GIVEUPOWNER, KILLTHREAD, RESERVED); ! 691: ! 692: /* Return the EGA adapter to a default mode that hopefully ! 693: * matches the mode that was present when we went into graphics ! 694: * mode. Then restore mode data, text screen data, cursor ! 695: * position and cursor type. ! 696: */ ! 697: ! 698: SetDVideo (); ! 699: if (graphics) { ! 700: /* clear display memory */ ! 701: dpoffset = 0; ! 702: SetScanClear (); ! 703: if (flip) ! 704: dpoffset = PAGESIZE; ! 705: SetScanClear (); ! 706: SetScanRFont (fontsel); ! 707: } ! 708: SetEVideo (); ! 709: VIOSETMODE ((struct ModeData far *)&mode, 0); ! 710: if (VIOWRTCELLSTR ((char far *)screenbuf, screenlen, 0, 0, 0) != 0) { ! 711: printf ("Unable to write text screen data\n"); ! 712: exit (1); ! 713: } ! 714: if (VIOSETCURPOS (currow, curcol, 0) != 0) { ! 715: printf ("Unable to set current cursor position\n"); ! 716: exit (1); ! 717: } ! 718: if (VIOSETCURTYPE ((struct CursorData *)&cursor, 0) != 0) { ! 719: printf ("Unable to set current cursor data\n"); ! 720: exit (1); ! 721: } ! 722: } ! 723: ! 724: ! 725: ! 726: /** nextimage ! 727: * ! 728: */ ! 729: ! 730: ! 731: nextimage () ! 732: { ! 733: int temp; ! 734: ! 735: if (head != tail) { ! 736: DOSSEMREQUEST ((unsigned long)(long far *)&drawsem, (long)-1); ! 737: if (curr->next == NULL) ! 738: curr = head; ! 739: else ! 740: curr = curr->next; ! 741: if (flip) ! 742: dpoffset ^= PAGESIZE; ! 743: SetScanRestore (curr->desc->savesel); ! 744: DOSSEMCLEAR ((unsigned long)(long far *)&drawsem); ! 745: } ! 746: } ! 747: ! 748: ! 749: ! 750: /** previmage ! 751: * ! 752: */ ! 753: ! 754: ! 755: previmage () ! 756: { ! 757: int temp; ! 758: ! 759: if (head != tail) { ! 760: DOSSEMREQUEST ((unsigned long)(long far *)&drawsem, (long)-1); ! 761: VIOSCRLOCK (1, (char far *)&temp, 0); ! 762: if (curr->prev == NULL) ! 763: curr = tail; ! 764: else ! 765: curr = curr->prev; ! 766: if (flip) ! 767: dpoffset ^= PAGESIZE; ! 768: SetScanRestore (curr->desc->savesel); ! 769: VIOSCRUNLOCK (0); ! 770: DOSSEMCLEAR ((unsigned long)(long far *)&drawsem); ! 771: } ! 772: } ! 773: ! 774: ! 775: ! 776: ! 777: /** ripple - ripple palette registers ! 778: * ! 779: * ripple (direction); ! 780: * ! 781: * Entry direction = 0 if rotate palette registers up ! 782: * direction = 1 if rotate palette registers down ! 783: * Exit palette registers rotated by one ! 784: * Returns none ! 785: */ ! 786: ! 787: ! 788: ripple (dir) ! 789: int dir; ! 790: { ! 791: int temp; ! 792: int i; ! 793: ! 794: switch (dir) { ! 795: case RIPPLE_UP: ! 796: temp = palette[0x0f]; ! 797: for (i = 0x0f; i > 1; i--) ! 798: palette[i] = palette[i - 1]; ! 799: palette[1] = temp; ! 800: break; ! 801: ! 802: case RIPPLE_DN: ! 803: temp = palette[1]; ! 804: for (i = 1; i < 0x0f; i++) ! 805: palette[i] = palette[i + 1]; ! 806: palette[0x0f] = temp; ! 807: break; ! 808: } ! 809: DOSSEMREQUEST ((unsigned long)(long far *)&drawsem, (long)-1); ! 810: setpalette (palette); ! 811: DOSSEMCLEAR ((unsigned long)(long far *)&drawsem); ! 812: } ! 813: ! 814: ! 815: ! 816: ! 817: /** flicker - flicker palette value ! 818: * ! 819: * flicker (pal); ! 820: * ! 821: * Entry pal = index of register to flicker ! 822: * Exit palette register toggled between value and black ! 823: * until keyboard input ! 824: * Returns none ! 825: */ ! 826: ! 827: ! 828: flicker (pal) ! 829: int pal; ! 830: { ! 831: int temp; ! 832: int c; ! 833: ! 834: if ((pal > 0) && (pal < 0x10)) { ! 835: temp = palette[pal]; ! 836: while (!nextchar (&c, 1)) { ! 837: palette[pal] = BLACK; ! 838: DOSSEMREQUEST ((unsigned long)(long far *)&drawsem, (long)-1); ! 839: setpalette (palette); ! 840: DOSSEMCLEAR ((unsigned long)(long far *)&drawsem); ! 841: DOSSLEEP ((long)100); ! 842: palette[pal] = temp; ! 843: DOSSEMREQUEST ((unsigned long)(long far *)&drawsem, (long)-1); ! 844: setpalette (palette); ! 845: DOSSEMCLEAR ((unsigned long)(long far *)&drawsem); ! 846: DOSSLEEP ((long)100); ! 847: } ! 848: ungetchar (); ! 849: } ! 850: } ! 851: ! 852: ! 853: ! 854: ! 855: ! 856: /** paledit - edit palette registers ! 857: * ! 858: * paledit (); ! 859: * ! 860: * Entry none ! 861: */ ! 862: ! 863: ! 864: paledit () ! 865: { ! 866: int pal; ! 867: int c; ! 868: ! 869: /* select palette register */ ! 870: ! 871: pal = 1; ! 872: flicker (pal); ! 873: while (TRUE) { ! 874: nextchar (&c, 0); ! 875: switch (-c) { ! 876: case UP: ! 877: if (pal++ > 0x0f) ! 878: pal = 1; ! 879: flicker (pal); ! 880: break; ! 881: ! 882: case DOWN: ! 883: if (pal-- < 1) ! 884: pal = 0x0f; ! 885: flicker (pal); ! 886: break; ! 887: ! 888: case RIGHT: ! 889: if (++palette[pal] > 0x3f) ! 890: palette[pal] = 1; ! 891: DOSSEMREQUEST ((unsigned long)(long far *)&drawsem, (long)-1); ! 892: setpalette (palette); ! 893: DOSSEMCLEAR ((unsigned long)(long far *)&drawsem); ! 894: break; ! 895: ! 896: case LEFT: ! 897: if (--palette[pal] == 0) ! 898: palette[pal] = 0x3f; ! 899: DOSSEMREQUEST ((unsigned long)(long far *)&drawsem, (long)-1); ! 900: setpalette (palette); ! 901: DOSSEMCLEAR ((unsigned long)(long far *)&drawsem); ! 902: break; ! 903: ! 904: default: ! 905: ungetchar (); ! 906: return; ! 907: } ! 908: } ! 909: } ! 910: ! 911: ! 912: ! 913: ! 914: /** nextchar - get next character from keyboard ! 915: * ! 916: * flag = nextchar (pchar, wait); ! 917: * ! 918: * Entry char = pointer to character return location ! 919: * wait = 0 if delay until character entered ! 920: * wait = 1 if immediate return if no character ! 921: * Exit char = next character if found ! 922: * char = -scan code if extend character ! 923: * Return flag = TRUE if character read from keyboard ! 924: * flag = FALSE if no character read and immediate return ! 925: */ ! 926: ! 927: ! 928: nextchar (pchar, wait) ! 929: int *pchar; ! 930: int wait; ! 931: { ! 932: int ret; ! 933: ! 934: if (!chvalid) { ! 935: if ((ret = KBDCHARIN ((struct KeyData far *)&key, wait, 0)) != 0) { ! 936: cleandisplay (); ! 937: printf ("Error %d return from KBDCHARIN\n", ret); ! 938: exit (1); ! 939: } ! 940: firstread = TRUE; ! 941: if ((key.status & 0x40) != 0x40) ! 942: return (FALSE); ! 943: } ! 944: chvalid = FALSE; ! 945: if (key.char_code == 0x00) ! 946: /* process extended ASCII character */ ! 947: *pchar = -(int)key.scan_code; ! 948: else ! 949: *pchar = (int)key.char_code; ! 950: return (TRUE); ! 951: } ! 952: ! 953: ! 954: ! 955: ! 956: ! 957: /** ungetchar - unget character from keyboard ! 958: * ! 959: * ungetchar (); ! 960: * ! 961: * Entry none ! 962: * Exit previous character returned to keyboard ! 963: * Return none ! 964: */ ! 965: ! 966: ! 967: ungetchar () ! 968: { ! 969: if (firstread) ! 970: chvalid = TRUE; ! 971: } ! 972: ! 973: ! 974: ! 975: ! 976: /** setpalette - set EGA palette registers ! 977: * ! 978: * setpalette (palette); ! 979: * ! 980: * Entry palette = byte array of palette registers ! 981: * Exit palette registers written to EGA ! 982: * Return none ! 983: */ ! 984: ! 985: ! 986: setpalette (p) ! 987: char *p; ! 988: { ! 989: int *ip; ! 990: ! 991: vstate.length = sizeof (struct VIOSTATE); ! 992: vstate.req_type = 0; ! 993: vstate.double_defined = 0; ! 994: for (ip = &vstate.palette0; ip <= &vstate.palette15; ) ! 995: *ip++ = *p++; ! 996: if (VIOSETSTATE ((struct VIOSTATE far *)&vstate, 0) != 0) { ! 997: cleandisplay (); ! 998: printf ("Unable to set palette registers\n"); ! 999: exit (1); ! 1000: } ! 1001: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.