Annotation of os2sdk/demos/apps/mandel/mdraw.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.