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

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

unix.superglobalmegacorp.com

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