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