Annotation of os2sdk/demos/apps/mandel/mdraw.c, revision 1.1.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.