home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / povsrc.sit / MACHINE / IBMPC.ZIP / IBM.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-11  |  80.0 KB  |  2,463 lines

  1. /****************************************************************************
  2. *                   ibm.c
  3. *
  4. *  This module implements the IBM-PC specific routines for POV-Ray.
  5. *
  6. *  from Persistence of Vision Raytracer 
  7. *  Copyright 1992 Persistence of Vision Team
  8. *---------------------------------------------------------------------------
  9. *  Copying, distribution and legal info is in the file povlegal.doc which
  10. *  should be distributed with this file. If povlegal.doc is not available
  11. *  or for more info please contact:
  12. *
  13. *       Drew Wells [POV-Team Leader] 
  14. *       CIS: 73767,1244  Internet: 73767.1244@compuserve.com
  15. *       Phone: (213) 254-4041
  16. * This program is based on the popular DKB raytracer version 2.12.
  17. * DKBTrace was originally written by David K. Buck.
  18. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  19. *
  20. *****************************************************************************/
  21.  
  22. /* Original IBM VGA "colour" output routines for MS/DOS by Aaron A. Collins.
  23.  
  24.    This will deliver approximate colorings using HSV values for the selection.
  25.    The palette map is divided into 4 parts - upper and lower half generated
  26.    with full and half "value" (intensity), respectively.  These halves are
  27.    further halved by full and half saturation values of each range (pastels).
  28.    There are three constant colors, black, white, and grey.  They are used
  29.    when the saturation is low enough that the hue becomes undefined, and which
  30.    one is selected is based on a simple range map of "value".  Usage of the
  31.    palette is accomplished by converting the requested color RGB into an HSV
  32.    value.  If the saturation is too low (< .25) then black, white or grey is
  33.    selected.  If there is enough saturation to consider looking at the hue,
  34.    then the hue range of 1-63 is scaled into one of the 4 palette quadrants
  35.    based on its "value" and "saturation" characteristics.
  36.  
  37.    Further SVGA, MVGA mods by Aaron A. Collins:
  38.    SVGA, MVGA assembler routines originally by John Bridges.
  39.    VESA assembler routines from FRACTINT, by The Stone Soup Group
  40.    AT&T VDC600 SVGA mods to DKB Trace 2.01 module IBM.C by John Gooding
  41.  
  42.    This file now represents the collective wisdom of the VGAKIT34 package,
  43.    with support for all of the SVGA types known to mankind.  Seriously,
  44.    VGAKIT34 is an excellent technical reference for IBM programmers wishing
  45.    to do any sort of SVGA video access, and it encompasses nearly all of the
  46.    SVGA adapters in use today.  It was written by John Bridges, a.k.a.
  47.    CIS:73307,606, GENIE:J.BRIDGES.  It was originally coded in IBM 80x86
  48.    assembler, and since DKBTrace is a completely "C"-based package, I have
  49.    converted John's assembler routines all into "C".  These may be a tad bit
  50.    slower, but they should be compatible across a wide variety of 80x86/(S)VGA
  51.    machines.  Note if you have a regular cheapo VGA card like myself, included
  52.    is "MODE13x" or MVGA (modified VGA) mode (some call it "tweaked", but I
  53.    call it "Simulated SVGA"), which gives 360x480 on any reasonably register-
  54.    compatible plain vanilla VGA card.  This mode gives a good simulated 640 by
  55.    480 screen resolution.  I did not implement all the neat hi-res modes of
  56.    all the various SVGA adapters, if you select a trace size bigger than the
  57.    program and/or card can handle (most likely 640x480), it is dynamically
  58.    scaled to fit the available resolution, so you'll be able to see a rough
  59.    approximation of an 800x600 trace even on any el-cheapo VGA card at 320x200
  60.    resolution.  The VESA VGA mode was freely adapted from FRACTINT, whose GIF
  61.    reading routines we are already using in DKBTrace.  I hope my conversion
  62.    of it works properly.
  63.  
  64.    There is still a reported problem with the EVEREX autodetect returning
  65.    TRIDENT.  In fact EVEREX uses a TRIDENT chip set, but apparently there
  66.    is some difference in operation.  There are cryptic diagnostic messages
  67.    such as T0000, etc. printed as a result of the autodetection routines
  68.    to help track down why the error is happening.  If you are experiencing
  69.    problems with EVEREX or TRIDENT, make note of the letter-4 digit code you
  70.    are given.  There is now an autodetect for VDC600 that I hope will work
  71.    universally.  A similar problem as the EVEREX exists, in that the VDC600
  72.    is detected as a PARADISE because it uses the PARADISE chip set.  I am now
  73.    looking for what I believe to be the model number in the BIOS ROM of the
  74.    VDC600 to differentiate between the two.  I hope this works  with all
  75.    VDC600's, as I only had one example to work from.  Please send all bug
  76.    reports to Aaron Collins at the "You Can Call Me RAY" BBS, the number is
  77.    in the authors.txt document.
  78.  
  79.  
  80.    POV-Ray Enhancements:
  81.  
  82.    (S)VGA B&W 64 Greyscale code courtesy of Grant Hess 6/21/91
  83.  
  84.    16/24-bit HGWS/TIGA/TRUECOLOR code courtesy of Jay S. Curtis 11/15/90
  85.  
  86.    VGA "332" palette routines courtesy of Alexander Enzmann 7/20/91
  87.  
  88.    Additional support for VESA and Tseng Labs 256 and 32768 color modes by
  89.    Charles Marslett  (CIS: 75300,1636).  Resolution is selected to be the
  90.    lowest possible and still fit the image entirely on the screen. 4/28/91
  91.  
  92.    ATI VGA Wonder XL Support for 32,768 color mode and all other SVGA modes
  93.    by Randy Antler.  Also image centering, outline box, and forces SVGA mode
  94.    for small images.  Minor bug fixes and cleanups as well. 9/11/91
  95.  
  96.    Combined IBMPRO.C and IBM.C into 1 file. 
  97.    B.Pulver 10/20/91
  98.  
  99.    Corrected defects in the centering and high color support for VESA modes
  100.    (particularly necessary for the newer 24-bit color cards and S3 based
  101.    Windows accellerator cards) -- Charles Marslett, 12/8/91 to 4/25/92.
  102.  
  103. */
  104.  
  105. #define DITHERED        /* Defined to test Doug Muir's dithering code */
  106.  
  107. #include <dos.h>        /* MS-DOS specific - for int86() REGS struct, etc. */
  108. #include <stdarg.h>
  109. #include <time.h>
  110. #include "frame.h"
  111. #include "povproto.h"
  112.  
  113.  
  114. #ifndef _INTELC32_
  115. #ifndef __386__
  116. #ifndef GCCDOS
  117.   #include "tiga.h"       /* HGWS/TIGA function library include file */
  118.   #include "tigadefs.h"   /* HGWS/TIGA function library include file */
  119.   #include "extend.h"     /* HGWS/TIGA function library include file */
  120. #endif
  121. #endif
  122. #endif
  123.  
  124. #ifdef __TURBOC__
  125.   extern unsigned _stklen = 12288; /* fairly large stack for HEAVY recursion */
  126.   #define CLD asm cld
  127.   #define _asm asm
  128.   #define _far far
  129. #else
  130. #ifdef __WATCOMC__
  131.   #define CLD clear_direction()
  132.   unsigned short __8087cw = IC_AFFINE | RC_NEAR | PC_64  | 0x007F;
  133.   void clear_direction(void);
  134.   #pragma aux clear_direction = 0xFC parm [] modify nomemory;
  135. #ifdef __386__
  136.   #define ax eax
  137.   #define bx ebx
  138.   #define cx ecx
  139.   #define dx edx
  140.   #define di edi
  141.   #define int86 int386
  142.   #define int86x int386x
  143. #endif
  144. #else
  145.  
  146. #ifdef _INTELC32_
  147.   #pragma interrupt (int10)
  148.   #pragma noansi
  149.   #include <stk.h>
  150.   #define CLD cld()
  151.  
  152.   void int10();
  153.   void (*prev_int10)();
  154.  
  155.   void cld (void)
  156.   {
  157.     unsigned int flags;
  158.     flags = _getflags();
  159.     flags = flags & (!_FLAG_DIRECTION);
  160.     _setflags (flags);
  161.   }
  162. #else
  163. #ifdef __ZTC__
  164.   #include <math.h>
  165.   #include <int.h>
  166.  
  167.   unsigned _stack = 12032;
  168.  
  169.   #define CLD
  170.   #define min(x,y) ((x) < (y)? (x): (y))
  171.  
  172.   #ifdef DOS386
  173.     extern unsigned short _x386_zero_base_selector;
  174.     #define _disable()
  175.     #define _enable()
  176.     #define _cdecl
  177.   #else
  178.   #ifdef DOS16RM
  179.     void *D16SegAbsolute(long absadr, short size);
  180.     void D16SegCancel(void *segptr);
  181.     #define _disable()
  182.     #define _enable()
  183.     unsigned char *display_base;
  184.   #else
  185.     #define _disable() int_off()
  186.     #define _enable()  int_on()
  187.   #endif
  188.   #endif
  189.  
  190. #else
  191. #ifdef GCCDOS
  192.   #include <errno.h>
  193.   #include <pc.h>
  194.   #include <ctype.h>
  195.  
  196.   unsigned char *find_go32(int *go32_offset);
  197.  
  198.   #define _cdecl
  199.   #define _far
  200.   #define CLD
  201. #else
  202.   #define CLD _asm cld
  203. #endif
  204. #endif
  205. #endif
  206. #endif
  207. #endif
  208.  
  209. #ifdef __WATCOMC__
  210.   int matherr(struct exception *);
  211. #else
  212. #ifdef GCCDOS
  213.   int matherr(struct libm_exception *);
  214. #else
  215.   int _cdecl matherr(struct exception *);
  216. #endif
  217. #endif
  218.  
  219.  
  220. #ifdef DITHERED
  221. signed char r_err[2][1026];             /* Allow up to 1024x??? resolutions */
  222. signed char g_err[2][1026];
  223. signed char b_err[2][1026];
  224. #endif
  225.  
  226. /* The supported VGA adapter types 1 - 9, A - Z.  0 is for auto-detect. */
  227.  
  228. #define BASIC_VGA       1               /* 1 - Tested: AAC */
  229. #define MODE13x         2               /* 2 - Tested: AAC */
  230. #define TSENG3          3               /* 3 - Tested: William Minus */
  231. #define TSENG4          4               /* 4 - Tested: William Minus */
  232. #define VDC600          5               /* 5 - Tested: John Gooding */
  233. #define OAKTECH         6               /* 6 - Untested */
  234. #define VIDEO7          7               /* 7 - Untested */
  235. #define CIRRUS          8               /* 8 - Tested: AAC */
  236. #define PARADISE        9               /* 9 - Tested: John Degner */
  237. #define AHEADA          17              /* A - Untested */
  238. #define AHEADB          18              /* B - Untested */
  239. #define CHIPSTECH       19              /* C - Untested */
  240. #define ATIVGA          20              /* D - Tested: William Earl */
  241. #define EVEREX          21              /* E - Tested: A+B problem - Larry Minton */
  242. #define TRIDENT         22              /* F - Tested: A problem - Alexander Enzmann */
  243. #define VESA            23              /* G - Tested: Charles Marslett/AAC */
  244. #define ATIXL           24              /* H - Tested: Randy Antler */
  245.  
  246. #define TRUECOLOR       31              /* #O or higher isn't an (S)VGA */
  247. #define TIGA_16         32              /* O - Tested: Jay S. Curtis */
  248. #define TIGA_24         33              /* P - Tested: Jay S. Curtis */
  249. #define TRUE_640        34              /* Q - 640 x 480 truecolor Tested: Jay S. Curtis */
  250. #define TRUE_800        35              /* R - 800 x 600 truecolor Tested: Jay S. Curtis */
  251. #define TRUE_1024       36              /* S - 1024 x 768 truecolor Tested: Jay S. Curtis */
  252.  
  253.  
  254. #define MISCOUT         0x3c2           /* VGA chip msic output reg. addr */
  255. #define SEQUENCER       0x3c4           /* VGA chip sequencer register addr */
  256. #define CRTC            0x3d4           /* VGA chip crt controller reg addr */
  257.  
  258.  
  259. char *vga_names[] = 
  260.     {
  261.     "",                                 /* '0' is autodetect */
  262.     "Standard VGA",                     /* '1'-'9' */
  263.     "Simulated SVGA",
  264.     "Tseng Labs 3000 SVGA",
  265.     "Tseng Labs 4000 SVGA",
  266.     "AT&T VDC600 SVGA",
  267.     "Oak Technologies SVGA",
  268.     "Video 7 SVGA",
  269.     "Video 7 Vega (Cirrus) VGA",
  270.     "Paradise SVGA",
  271.     "",                                 /* misc ASCII */
  272.     "",
  273.     "",
  274.     "", /* reserved */
  275.     "",
  276.     "",
  277.     "",
  278.     "Ahead Systems Ver. A SVGA",        /* 'A' - 'H' */
  279.     "Ahead Systems Ver. B SVGA",
  280.     "Chips & Technologies SVGA",
  281.     "ATI SVGA",
  282.     "Everex SVGA",
  283.     "Trident SVGA",
  284.     "VESA Standard SVGA",
  285.     "ATI VGA Wonder XL 32K Color SVGA",
  286.     "",
  287.     "",
  288.     "", /* spare SVGAs */
  289.     "",
  290.     "",
  291.     "",
  292.     "Hercules GWS/TIGA 16-bit", /* 'O' on is reserved for non-SVGA cards */
  293.     "Hercules GWS/TIGA 24-bit",
  294.     "TrueColor 640 x 480",
  295.     "TrueColor 800 x 600",
  296.     "TrueColor 1024 x 768"
  297.     };
  298.  
  299.  
  300. unsigned int vptbl[] =          /* CRTC register values for MODE13x */
  301.     {
  302.     0x6b00,     /* horz total */
  303.     0x5901,     /* horz displayed */
  304.     0x5a02,     /* start horz blanking */
  305.     0x8e03U,    /* end horz blanking */
  306.     0x5e04,     /* start h sync */
  307.     0x8a05U,    /* end h sync */
  308.     0x0d06,     /* vertical total */
  309.     0x3e07,     /* overflow */
  310.     0x4009,     /* cell height */
  311.     0xea10U,    /* v sync start */
  312.     0xac11U,    /* v sync end and protect cr0-cr7 */
  313.     0xdf12U,    /* vertical displayed */
  314.     0x2d13,     /* offset */
  315.     0x0014,     /* turn off dword mode */
  316.     0xe715U,    /* v blank start */
  317.     0x0616,     /* v blank end */
  318.     0xe317U     /* turn on byte mode */
  319. };
  320.  
  321. int screen_height, screen_width;
  322. int svga_width = 640;           /* width of a scan line on the screen */
  323. int svga_height = 480;          /* number of scan lines on the screen */
  324. int svga_yincr = 640;           /* width of a scan line in video memory */
  325. int lastx, lasty, lastline;     /* Pixel / Line Caches */
  326. unsigned int x_off = 0;         /* Offsets for image centering option */
  327. unsigned int y_off = 0;
  328. int whichvga = BASIC_VGA;       /* BASIC_VGA mode by default */
  329. int vga_512K = FALSE;           /* Flag for whether or not >= 512K VGA mem */
  330. int bpp = 8;                    /* Number of bits per pixel */
  331. unsigned char cur_page = 255;   /* SVGA current page (bank) number */
  332. unsigned int map_code = 0;      /* default map code is 0 */
  333. unsigned long gran = 65536L;    /* SVGA granule size (64K by default) */
  334. #ifdef _INTELC32_
  335. unsigned char *answer;          /* answer area for VESA BIOS calls */
  336. #else
  337. #ifdef DOS16RM
  338. unsigned char *answer;          /* answer area for VESA BIOS calls */
  339. static char save[260];
  340. unsigned long tl;
  341. #else
  342. #ifdef GCCDOS
  343. volatile unsigned char *answer; /* answer area for VESA BIOS calls */
  344. int di_val;
  345. #else
  346. #ifdef __WATCOMC__
  347. #ifdef __386__
  348. unsigned int vesabuffer;        /* save area for the DOS segment pointer */
  349. unsigned char *answer;          /* answer area for VESA BIOS calls */
  350. #else
  351. unsigned char answer[257];      /* answer area for VESA BIOS calls */
  352. #endif
  353. #else
  354. unsigned char answer[257];      /* answer area for VESA BIOS calls */
  355. #endif
  356. #endif
  357. #endif
  358. #endif
  359. int vesamode;                   /* cur. VESA BIOS supported mode */
  360.  
  361. int dither_matrix[4][4]=
  362.     {{0,8,2,10},            /* HGWS/TIGA dither matrix */
  363.      {12,4,14,6},           /* this may not be needed? */
  364.      {3,11,1,9},
  365.      {15,7,13,5}
  366.     };
  367. char hpt[3];                    /* HWGS/TIGA information passing area */
  368. char _far *hptr=hpt;            /* HWGS/TIGA information passing area ptr */
  369. #ifndef _INTELC32_
  370. #ifndef __386__
  371. #ifndef GCCDOS
  372. CONFIG config;
  373. #endif
  374. #endif
  375. #endif
  376. DBL Height_Adjust = 1.0;        /* fudge factors for SVGA scaling */
  377. DBL Width_Adjust = 1.0;
  378.  
  379. /* VESA VBE standard mode numbers */
  380.  
  381. struct {
  382.    unsigned short modenum;
  383.    unsigned short width;
  384.    unsigned short height;
  385.    unsigned short bpp;
  386.    unsigned short gsize;
  387.    } modelist[] = {{0x100, 640, 400, 8, 0}, {0x101, 640, 480, 8, 0},
  388.            {0x103, 800, 600, 8, 0}, {0x105, 1024, 768, 8, 0},
  389.            {0x107, 1280, 1024, 8, 0}, {0x10D, 320, 200, 16, 5},
  390.            {0x10E, 320, 200, 16, 6}, {0x10F, 320, 200, 24, 8},
  391.            {0x110, 640, 480, 16, 5}, {0x111, 640, 480, 16, 6},
  392.            {0x112, 640, 480, 24, 8}, {0x113, 800, 600, 16, 5},
  393.            {0x114, 800, 600, 16, 6}, {0x115, 800, 600, 24, 8},
  394.            {0x116, 1024, 768, 16, 5}, {0x117, 1024, 768, 16, 6},
  395.            {0x118, 1024, 768, 24, 8}, {0x119, 1280, 1024, 16, 5},
  396.            {0x11A, 1280, 1024, 16, 6}, {0x11B, 1280, 1024, 24, 8}};
  397.  
  398. unsigned int bitmask[] = {0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F,
  399.       0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF,
  400.       0x7FFF, 0xFFFF};
  401.  
  402. int r_shift, g_shift, b_shift;
  403. unsigned int r_mask, g_mask, b_mask;
  404.  
  405.  
  406. extern unsigned int Options;
  407. extern char DisplayFormat, PaletteOption, Color_Bits;
  408.  
  409.  
  410. int AutodetectVGA(void);
  411. int cirrus(void);
  412. int chkbank(unsigned int, unsigned int);
  413. void palette_init(void);
  414. void newbank(void);
  415. void set_palette_register(unsigned, unsigned, unsigned, unsigned);
  416. void hsv_to_rgb(DBL, DBL, DBL, unsigned *, unsigned *, unsigned *);
  417. void rgb_to_hsv(unsigned, unsigned, unsigned, DBL *, DBL *, DBL *);
  418. void atiplot(int, int, int, int, int);
  419. void atibank(int);
  420. void box(int, int, int, int);
  421. int _cdecl box_fprintf( FILE *stream, char *format,...);
  422.  
  423. #ifdef DOS386
  424. void get_real_buf(short *real_buf, unsigned char _far **ptr);
  425.  
  426. static short real_buf[2];
  427. static unsigned char _far *real_ptr;
  428. #endif
  429.  
  430. void display_init(width, height) /* Set video to requested or best mode */
  431. int width, height;
  432.    {
  433.    union REGS inr, outr;
  434.    struct SREGS segs;
  435.    unsigned char _far *fp;
  436. #ifdef DOS386
  437.    unsigned int tmp_word;
  438. #else
  439.    unsigned short _far *mp;
  440. #endif
  441.    unsigned int u, granule, vesamodes[64];
  442. /* unsigned int tmp_word, tmp_word1; */
  443.    int i, maxvesamode;
  444.    time_t l, lt;
  445.    int show_display_type = FALSE;
  446.  
  447.    if (DisplayFormat == '?'){  
  448.       DisplayFormat = '0';
  449.       show_display_type = TRUE;
  450.       }
  451. #ifdef __WATCOMC__
  452. #ifdef __386__
  453.    inr.x.ax = 0x4800;
  454.    inr.x.bx = 17;
  455.    int86(0x21, &inr, &outr);
  456.    vesabuffer = outr.x.ax;
  457.    answer = MK_FP(outr.x.ax, 0);
  458. #endif
  459. #endif
  460. #ifdef DOS16RM
  461.    display_base = (unsigned char *)D16SegAbsolute(0xA0000, 0);
  462.    answer = (unsigned char *)D16SegAbsolute(0x00580, 0x110);
  463.    for (u=0; u < 257; u++)
  464.       save[u] = answer[u];
  465. #endif
  466. #ifdef GCCDOS
  467.    if (DisplayFormat == '0' || DisplayFormat == VESA + '0')
  468.       answer = find_go32(&di_val);
  469.    else
  470.       answer = NULL;
  471. #endif
  472. #ifdef _INTELC32_
  473.    prev_int10 = _dos_getvect ( 0x10 );     /* Save previous handler pointer */
  474.    _dos_setvect ( 0x80000010, int10 );     /* Install user Int 10h handler */
  475.    if (_dos_allocmem(17, &answer) != 0) { 
  476.       printf ("Memory allocation failure for VESA detect.\n");
  477.       exit(0);
  478.       }
  479. #endif
  480. #ifdef DOS386
  481.    get_real_buf(real_buf, &real_ptr);
  482. #endif
  483.  
  484.    lastline = -1;               /* make sure we display the 1st line... */
  485.    screen_height = height;      /* requested screen height and width */
  486.    screen_width = width;
  487.  
  488. #ifdef DITHERED
  489.    for (i=0; i < screen_width+2; i++) {
  490.       r_err[0][i] = 0;
  491.       r_err[1][i] = 0;
  492.       g_err[0][i] = 0;
  493.       g_err[1][i] = 0;
  494.       b_err[0][i] = 0;
  495.       b_err[1][i] = 0;
  496.       }
  497. #endif
  498.     
  499.    if (DisplayFormat != '0')    /* if not 0, some display type specified */
  500.     whichvga = (int)(DisplayFormat - '0');  /* de-ASCII-fy selection */
  501.    else {
  502.     whichvga = AutodetectVGA();
  503.     lt = l = time(&l);
  504.     if (show_display_type) {   /* If display format is ? */
  505.         printf("Display detected: (%c) %s Adapter", whichvga + '0', vga_names[whichvga]);
  506.         if (whichvga < TRUECOLOR)   /*  if not a True-Color graphics card */
  507.         printf(", with %s 512K RAM\n", vga_512K ? ">=" : "<");
  508.         else
  509.         printf("\nPausing...\n");
  510.         while (time(&l) < lt + 5)   /* display detected VGA type for 5 secs */
  511.            ;
  512.         }
  513.     if (!vga_512K)                  /* not enough RAM for 640 x 480? */
  514.         whichvga = MODE13x;         /* then try for next best mode... */
  515.     }
  516.  
  517.    if (whichvga < TRUECOLOR) /* If an (S)VGA (not True-Color graphics card) */
  518.     {
  519.     if (whichvga == CIRRUS) /* Register Compatible VGA? */
  520.         whichvga = MODE13x; /* MODE13x if > 320x200, else... */
  521.  
  522.     if (screen_height <= 200 && screen_width <= 320 && PaletteOption != HICOLOR)
  523.         whichvga = BASIC_VGA;
  524.  
  525.     if (whichvga == TSENG4 && PaletteOption == HICOLOR)
  526.         {
  527.         inr.x.ax = 0x10F1;          /* check and see if it's true... */
  528. #ifdef DOS386
  529.         int86_real(0x10, &inr, &inr);
  530. #else
  531.         int86(0x10, &inr, &inr);
  532. #endif
  533.         if ((int) inr.h.al != 0x10 || (int)inr.h.bl == 0)
  534.         {
  535.         printf("Error - High Color Palette Option Unavailable\n");
  536.         exit(1);
  537.         }
  538.         }
  539.     }
  540.  
  541.    switch (whichvga)
  542.     {
  543.     case MODE13x:
  544.         inr.x.ax = 0x0013;   /* setup to VGA 360x480x256 (mode 13X) */
  545.         svga_width = 360;           /* Fake 640 mode actually is 360 */
  546.         svga_yincr = 90;
  547.         break;
  548.     case VDC600:
  549.         inr.x.ax = 0x005E;   /* setup to VGA 640x400x256 (mode 5EH) */
  550.         svga_height = 400;   /* This is the only SVGA card w/400 Lines */
  551.         break;
  552.     case OAKTECH:
  553.         inr.x.ax = 0x0053;   /* setup to VGA 640x480x256 most SVGAs */
  554.         break;
  555.     case AHEADA:
  556.     case AHEADB:
  557.         inr.x.ax = 0x0061;
  558.         break;
  559.     case EVEREX:
  560.         inr.x.ax = 0x0070;   /* BIOS Mode 0x16 for EV-678? */
  561.         inr.h.bl = 0x30;
  562.         break;
  563.     case ATIVGA:
  564.         if (screen_width <= 1024 && screen_height <= 768)
  565.         {
  566.         inr.x.ax = 0x0064;
  567.         svga_width = 1024;
  568.         svga_height = 768;
  569.         svga_yincr = 1024;
  570.         }
  571.         if (screen_width <= 800 && screen_height <= 600)
  572.         {
  573.         inr.x.ax = 0x0063;
  574.         svga_width = 800;
  575.         svga_height = 600;
  576.         svga_yincr = 800;
  577.         }
  578.         if (screen_width <= 640 && screen_height <= 480)
  579.         {
  580.         inr.x.ax = 0x0062;
  581.         svga_width = 640;
  582.         svga_height = 480;
  583.         svga_yincr = 640;
  584.         }
  585.         break;
  586.     case ATIXL:
  587.         inr.x.ax = 0x0072;
  588.         svga_width = 640;
  589.         svga_height = 480;
  590.         svga_yincr = 640;
  591.         break;
  592.     case TRIDENT:
  593.         inr.x.ax = 0x005d;
  594.         break;
  595.     case VIDEO7:
  596.         inr.x.ax = 0x6f05;
  597.         inr.h.bl = 0x67;
  598.         break;
  599.     case CHIPSTECH:
  600.         if (screen_height <= 400)
  601.         {
  602.            inr.x.ax = 0x0078;
  603.            svga_height = 400;
  604.         }
  605.         else
  606.         inr.x.ax = 0x0079;
  607.         break;
  608.     case PARADISE:
  609.         inr.x.ax = 0x005f;
  610.         break;
  611.     case TSENG3:
  612.     case TSENG4:
  613.         if (screen_height <= 200 && screen_width <= 320)
  614.         {
  615.          inr.x.ax = 0x0013;  /* setup to VGA 320x200 for 32K mode  */
  616.          svga_width = 320;   /* allow scaling to run at 320x200 */
  617.          svga_height = 200;
  618.          svga_yincr = 320;
  619.         }
  620.         else if (screen_height <= 350 && screen_width <= 640)
  621.         {
  622.          inr.x.ax = 0x002D;
  623.          svga_height = 350;
  624.         }
  625.         else if (screen_height <= 400 && screen_width <= 640 && whichvga == TSENG4)
  626.         {
  627.          inr.x.ax = 0x0078;
  628.          svga_height = 400;
  629.         }
  630.         else if (screen_height <= 480 && screen_width <= 640)
  631.         {
  632.          inr.x.ax = 0x002E;
  633.         }
  634.         else        /* 800 by 600 and beyond */
  635.         {
  636.          inr.x.ax = 0x0030;
  637.          svga_width = 800;
  638.          svga_height = 600;
  639.          svga_yincr = 800;
  640.         }
  641.         if ((screen_height > 600 || screen_width > 800) && whichvga == TSENG4)
  642.         {
  643.         if (PaletteOption == HICOLOR)
  644.         {
  645.             inr.x.ax = 0x0030; /* Limit to 800x600 in HiColor mode */
  646.             svga_width = 800;
  647.             svga_height = 600;
  648.             svga_yincr = 800;
  649.         }
  650.         else
  651.         {
  652.             inr.x.ax = 0x0038;
  653.             svga_width = 1024;
  654.             svga_height = 768;
  655.             svga_yincr = 1024;
  656.         }
  657.         }
  658.         break;
  659.     case VESA:
  660.         inr.x.ax = 0x4F00;      /* Call function 0 to get VGA info */
  661. #ifdef _INTELC32_
  662.         for (u=0; u<256; u++)
  663.         answer[u] = 0;
  664.         inr.w.edi = (unsigned)answer;  
  665.         int86(0x10, &inr, &outr);         /* Get thru int 10h inr outr */
  666. #else
  667. #ifdef DOS386
  668.         for (u=0; u<256; u++)
  669.         real_ptr[u] = 0;
  670.         inr.x.di = real_buf[0];         /* deposit results here */
  671.         segread(&segs);                 /* get our DS, etc. */
  672.         segs.es = real_buf[1];          /* get segment of answer */
  673.         int86x_real(0x10, &inr, &outr, &segs);
  674.         for(u=0; u<sizeof(answer); u++)
  675.         answer[u] = real_ptr[u];
  676. #else
  677. #ifdef GCCDOS
  678.         for (u=0; u<256; u++)
  679.         answer[u] = 0;
  680.         inr.x.di = di_val;              /* deposit results here */
  681.         int86x(0x10, &inr, &outr, &segs);
  682. #else
  683. #ifdef DOS16RM
  684.         for (u=0; u<256; u++)
  685.         answer[u] = 0;
  686.         segread(&segs);                 /* get our DS, etc. */
  687.         inr.x.di = 0x580;               /* deposit results here */
  688.         segs.es = 0;                    /* get segment of answer */
  689.         int86x(0x10, &inr, &outr, &segs);
  690. #else
  691.         for (u=0; u<256; u++)
  692.         answer[u] = 0;
  693.         inr.x.di = FP_OFF(answer);      /* deposit results here */
  694.         segread(&segs);                 /* get our DS, etc. */
  695.         segs.es = FP_SEG(answer);       /* get segment of answer */
  696.         int86x(0x10, &inr, &outr, &segs);
  697. #endif
  698. #endif
  699. #endif
  700. #endif
  701.         if ( outr.x.ax != 0x004F || answer[0] != 'V' ||
  702.             answer[1] != 'E' || answer[2] != 'S' ||
  703.             answer[3] != 'A' )
  704.         {                      /* if response unsuccessful */
  705.         printf("Error - VESA BIOS Extensions Not Available: code=%04X<%c%c%c%c>\n",
  706.             outr.x.ax, answer[0],answer[1],answer[2],answer[3]);
  707. #ifdef DOS16RM
  708.         for (u=0; u < 257; u++)
  709.             answer[u] = save[u];
  710. #endif
  711. #ifdef _INTELC32_
  712.         _dos_setvect(0x10, prev_int10);/* Restore previous handler */
  713.         _dos_freemem((unsigned) answer);/* Free DOS buffer */
  714. #endif
  715.         exit(1);
  716.         }
  717. #ifdef _INTELC32_
  718.         mp = (char *)(*(unsigned short *)(answer + 14) +
  719.              (((long)*(unsigned short *)(answer + 16)) << 4));
  720.         for (i = 0; i < 64 && mp[i] != 0xFFFF; i++) /* for all modes available */
  721.         vesamodes[i] = mp[i];           /* copy to local mode list */
  722. #else
  723. #ifdef DOS386
  724.         fp = MK_FP(_x386_zero_base_selector,
  725.         *(unsigned short *)(answer+14)  /* get mode tbl. pointer   */
  726.         + (*(unsigned short *)(answer+16) << 4));
  727.         for (u=i=0; i < 64 && (tmp_word=fp[u]|(fp[u+1]<<8)) != 0xFFFF; i++, u += 2)/* for all modes available */
  728.         vesamodes[i] = tmp_word;        /* copy to local mode list */
  729. #else
  730. #ifdef DOS16RM
  731.         tl = *(unsigned short *)(answer + 14) +
  732.           (((long)*(unsigned short *)(answer + 16)) << 4);
  733.         mp = (unsigned short *)D16SegAbsolute(tl, 0);
  734.         for (i = 0; i < 64 && mp[i] != 0xFFFF; i++) /* for all modes available */
  735.         vesamodes[i] = mp[i];           /* copy to local mode list */
  736.         D16SegCancel((void *)mp);
  737. #else
  738.         mp = (unsigned short *)MK_FP(answer[16]+(answer[17]<<8),
  739.                answer[14]+(answer[15]<<8)); /* get mode tbl. pointer */
  740.         for (i = 0; i < 64 && mp[i] != 0xFFFF; i++)   /* for all modes available */
  741.         vesamodes[i] = mp[i];           /* copy to local mode list */
  742. #endif
  743. #endif
  744. #endif
  745.         maxvesamode = i;                    /* note end of list */
  746.         bpp = (PaletteOption == HICOLOR)? 16: (PaletteOption == FULLCOLOR)? 32: 8;
  747.  
  748.         svga_width = 0;
  749.         svga_height = 0;
  750.         vesamode = 0;
  751.         for (i = 0; i < maxvesamode; i++) {
  752.         inr.x.ax = 0x4F01;      /* VESA BIOS fetch attributes call */
  753.         inr.x.bx = inr.x.cx = vesamodes[i]; /* get attrs for mode */
  754. #ifdef DOS386
  755.         inr.x.di = real_buf[0];         /* deposit results here */
  756.         segread(&segs);                 /* get our DS, etc. */
  757.         segs.es = real_buf[1];          /* get segment of answer */
  758.         int86x_real(0x10, &inr, &outr, &segs);
  759.         for(u=0; u<sizeof(answer); u++)
  760.             answer[u] = real_ptr[u];
  761. #else
  762. #ifdef GCCDOS
  763.         inr.x.di = di_val;              /* deposit results here */
  764.         int86x(0x10, &inr, &outr, &segs);/* BIOS fetch attrib call */
  765. #else
  766. #ifdef DOS16RM
  767.         segread(&segs);                 /* get our DS, etc. */
  768.         inr.x.di = 0x580;               /* deposit results here */
  769.         segs.es = 0;
  770.         int86x(0x10, &inr, &outr, &segs);/* BIOS fetch attrib call */
  771. #else
  772.         inr.x.di = FP_OFF(answer);      /* deposit attribs here */
  773.         segread(&segs);                 /* get our DS, etc. */
  774.         segs.es = FP_SEG(answer);       /* get segment of answer */
  775.         int86x(0x10, &inr, &outr, &segs);/* BIOS fetch attrib call */
  776. #endif
  777. #endif
  778. #endif
  779.         if ((answer[0] & 0x11) != 0x11)
  780.             continue;
  781.         if ((answer[0] & 0x02) == 0) {
  782.             for (u=0; u < sizeof(modelist)/sizeof(modelist[0]); u++)
  783.             if (inr.x.cx == modelist[u].modenum) {
  784.                 *(unsigned short *)(answer+18) = modelist[u].width;
  785.                 *(unsigned short *)(answer+20) = modelist[u].height;
  786.                 answer[25] = modelist[u].bpp;
  787.                 answer[36] = 0;
  788.                 if (answer[25] == 16) {
  789.                 answer[31] = 5;
  790.                 answer[32] = modelist[u].gsize + 5;
  791.                 answer[33] = modelist[u].gsize;
  792.                 answer[34] = 5;
  793.                 answer[35] = 5;
  794.                 }
  795.                 else if (answer[25] == 24 || answer[25] == 32) {
  796.                 answer[31] = modelist[u].gsize;
  797.                 answer[32] = modelist[u].gsize * 2;
  798.                 answer[33] = modelist[u].gsize;
  799.                 answer[34] = modelist[u].gsize;
  800.                 answer[35] = modelist[u].gsize;
  801.                 }
  802.                 answer[0] |= 0x02;
  803.                 break;
  804.                 }
  805.             }
  806.         else if (bpp == 16 && answer[31] == 0 && answer[33] == 0 &&
  807.             answer[35] == 0) {
  808.             answer[31] = 5;     /* VESA 1.1 Programming guideline */
  809.             answer[32] = 10;    /* default high color is 5-5-5 */
  810.             answer[33] = 5;
  811.             answer[34] = 5;
  812.             answer[35] = 5;
  813.             }
  814.  
  815.         if ((answer[0] & 0x02) && (answer[25] == bpp ||
  816.             (bpp == 32 && answer[25] == 24))) {
  817.             if ((svga_height < screen_height || svga_width < screen_width) &&
  818.                 *(unsigned short *)(answer+18) >= svga_width &&
  819.                 *(unsigned short *)(answer+20) >= svga_height)
  820.                   vesamode = vesamodes[i];
  821.             else if (svga_height >= *(unsigned short *)(answer+18) &&
  822.                 svga_width >= *(unsigned short *)(answer+20) &&
  823.                 *(unsigned short *)(answer+18) >= screen_width &&
  824.                 *(unsigned short *)(answer+20) >= screen_height)
  825.                   vesamode = vesamodes[i];
  826.  
  827.             if (vesamode == vesamodes[i]) {
  828.             if ((answer[2] & 0x05) == 0x05)
  829.                 map_code = 0x0000;          /* Select A page */
  830.             else if ((answer[3] & 0x05) == 0x05)
  831.                 map_code = 0x0001;          /* Select B page */
  832.             bpp = answer[25];               /* Handle 24 or 32 bpp */
  833.                 svga_width = *(unsigned short *)(answer+18);
  834.                 svga_height = *(unsigned short *)(answer+20);
  835.                 r_shift = answer[32] + answer[31] - 8;
  836.                 g_shift = answer[34] + answer[33] - 8;
  837.                 b_shift = answer[36] + answer[35] - 8;
  838.                 r_mask = 0xFF - bitmask[8 - answer[31]];
  839.                 g_mask = 0xFF - bitmask[8 - answer[33]];
  840.                 b_mask = 0xFF - bitmask[8 - answer[35]];
  841.                 b_shift = - b_shift;
  842.                 if (bpp > 8 && (b_shift < 0 || r_shift < 0 || g_shift < 0)) {
  843.                     printf("Adapter not supported currently in high color modes!\n");
  844.                     printf("Shifts required are RED:%d, GREEN:%d, BLUE:%d\n",
  845.                         r_shift, g_shift, b_shift);
  846.                     printf("Bit masks: RED:%d, GREEN:%d, BLUE:%d\n",
  847.                         r_mask, g_mask, b_mask);
  848.                     printf("Field positions: RED:%d, GREEN:%d, BLUE:%d\n",
  849.                         answer[36], answer[34], answer[32]);
  850.                     printf("Field widths: RED:%d, GREEN:%d, BLUE:%d\n",
  851.                         answer[35], answer[33], answer[31]);
  852.                     exit(1);
  853.                     }
  854.                 }
  855.             }
  856.         }
  857.  
  858.         if (vesamode == 0)
  859.         goto no_valid_mode;
  860.  
  861.         inr.x.ax = 0x4F01;  /* VESA BIOS fetch attributes call */
  862.         inr.x.bx = inr.x.cx = vesamode;     /* get attrs for mode */
  863. #ifdef GCCDOS
  864.         inr.x.di = di_val;                  /* deposit results here */
  865.         int86x(0x10, &inr, &outr, &segs);
  866. #else
  867. #ifdef DOS386
  868.         inr.x.di = real_buf[0];             /* deposit results here */
  869.         segread(&segs);                     /* get our DS, etc. */
  870.         segs.es = real_buf[1];              /* get segment of answer */
  871.         int86x_real(0x10, &inr, &outr, &segs);
  872.         for(u=0; u<sizeof(answer); u++)
  873.         answer[u] = real_ptr[u];
  874. #else
  875. #ifdef DOS16RM
  876.         segread(&segs);                     /* get our DS, etc. */
  877.         inr.x.di = 0x580;                   /* deposit results here */
  878.         segs.es = 0;
  879.         int86x(0x10, &inr, &outr, &segs);
  880. #else
  881.         inr.x.di = FP_OFF(answer);  /* deposit attribs here */
  882.         segread(&segs);                     /* get our DS, etc. */
  883.         segs.es = FP_SEG(answer);   /* get segment of answer */
  884.         int86x(0x10, &inr, &outr, &segs);/* BIOS fetch attrib call */
  885. #endif
  886. #endif
  887. #endif
  888.         if (outr.x.ax != 0x004F)
  889.         goto no_valid_mode;
  890.         svga_yincr = *(unsigned short *)(answer+16);
  891.         granule = *(unsigned short *)(answer + 4); /* "granule" size */
  892.         if (granule < 1)
  893.         granule = 1;
  894.         gran = 1024L * granule;
  895.         inr.x.ax = 0x4F02;  /* VESA BIOS initialize video mode call */
  896.  
  897.         if (svga_yincr == svga_width && PaletteOption == HICOLOR)
  898.         if (svga_width == 640 && svga_height == 200) {
  899.             svga_width = 320;
  900.             svga_yincr = 1024;
  901.         }
  902.         else {
  903.             svga_yincr = svga_width * 2;
  904.         }
  905.         break;
  906.  
  907. #if !defined(DOS16RM) && !defined(DOS386) && !defined(_INTELC32_)
  908. #if !defined(__386__) && !defined(GCCDOS)
  909.  
  910.     case TIGA_16:
  911.     case TIGA_24:
  912.     case TRUE_640:
  913.     case TRUE_800:
  914.     case TRUE_1024:
  915.         if ((int)(DisplayFormat - '0') == whichvga) /* not autodetected */
  916.         if (tiga_set(CD_OPEN) < 0) /* Attempt to open the TIGA CD */
  917.             {
  918.             printf("Error - TIGA CD Not Installed.");
  919.             goto TIGA_error;
  920.             }
  921.         if (!set_videomode(TIGA, INIT_GLOBALS | CLR_SCREEN))
  922.         {
  923.         printf("Error #1 Initializing TIGA.");
  924.         goto TIGA_error;
  925.         }
  926.         if (install_primitives() < 0) /* load if not already loaded */
  927.         {
  928.         if (!set_videomode(TIGA, INIT)) /*reinit if due to full heap*/
  929.             {
  930.             printf("Error #2 Initializing TIGA.");
  931.             goto TIGA_error;
  932.             }
  933.         else if (install_primitives() < 0)
  934.             {
  935.             printf("Error Installing TIGA Primitives.");
  936. TIGA_error:
  937. #ifdef DOS16RM
  938.             for (u=0; u < 257; u++)
  939.             answer[u] = save[u];
  940. #endif
  941. #ifdef _INTELC32_
  942.             _dos_setvect(0x10, prev_int10);/* Restore previous handler */
  943.             _dos_freemem((unsigned) answer);/* Free DOS buffer */
  944. #endif
  945.             exit(1);
  946.             }
  947.         switch (whichvga)
  948.             {
  949.             case TIGA_16:       /* initialize demo globals */
  950.              get_config(&config);
  951.              if ((config.mode.disp_vres == 640) && (config.mode.disp_psize == 16))
  952.              {
  953.                 Color_Bits = 5;
  954.                 svga_width = 640;
  955.                 svga_height = 480;
  956.                 svga_yincr = 640;
  957.                 set_config(1,0);        /* 16 bit (was 2,0 ???? - AAC) */
  958.                 break;
  959.              }
  960.              else whichvga = TIGA_24;
  961.             case TIGA_24:
  962.             get_config(&config);
  963.             if ((config.mode.disp_vres == 480) && (config.mode.disp_hres == 512))
  964.             {
  965.                 svga_width = 512;   /* NTSC standard television resolution */
  966.                 svga_height = 480;
  967.                 svga_yincr = 512;
  968.                 set_config(4,0);       /* 24 bit */
  969.                 break;
  970.             }
  971.             else whichvga = TRUE_640;
  972.             case TRUE_640:
  973.             get_config(&config);
  974.             if ((config.mode.disp_hres == 640) && (config.mode.disp_psize == 32))
  975.             {
  976.                 svga_width = 640;
  977.                 svga_height = 480;
  978.                 svga_yincr = 640;
  979.                 set_config(0,0);       /* 24 bit */
  980.                 break;
  981.             }
  982.             else whichvga = TRUE_800;
  983.            case TRUE_800:
  984.             get_config(&config);
  985.             if ((config.mode.disp_vres == 600) && (config.mode.disp_hres == 800))
  986.             {
  987.                 svga_width = 800;
  988.                 svga_height = 600;
  989.                 svga_yincr = 800;
  990.                 set_config(2,0);       /* 24 bit */
  991.                 break;
  992.             }
  993.             else whichvga = TRUE_1024;
  994.            case TRUE_1024:
  995.             svga_width = 1024;
  996.             svga_height = 768;
  997.             svga_yincr = 1024;
  998.             set_config(4,0);
  999.            }
  1000.         }
  1001. #endif
  1002. #endif
  1003.         break;
  1004.  
  1005.     default:                /* BASIC_VGA */
  1006. no_valid_mode:
  1007.         inr.x.ax = 0x0013;  /* setup to VGA 320x200x256 (mode 13H) */
  1008.         svga_width = 320;   /* allow scaling to run at 320x200 */
  1009.         svga_height = 200;
  1010.         svga_yincr = 320;
  1011.         break;
  1012.     }
  1013. #ifdef DEBUG_VIDEO
  1014.     if (whichvga >= TRUECOLOR)  /* if True-Color then it has no palette */
  1015.         goto exit_point;
  1016.  
  1017.     lt = l = time(&l);
  1018.     printf("Display detected: (%c) %s Adapter", whichvga + '0', vga_names[whichvga]);
  1019.     if (whichvga < TRUECOLOR)   /*  if not a True-Color graphics card */
  1020.     printf(", with %s 512K RAM", vga_512K ? ">=" : "<");
  1021.     printf("\n   ax=%04X, bx=%04X, cx=%04X\n", inr.x.ax, inr.x.bx, inr.x.cx);
  1022.     printf("   %dx%d, yincr=%d\n", svga_width, svga_height, svga_yincr);
  1023.     printf("   shifts(R,G,B)=%d,%d,%d\n", r_shift, g_shift, -b_shift);
  1024.     printf("   masks(R,G,B) =%d,%d,%d\n", r_mask, g_mask, b_mask);
  1025.     while (time(&l) < lt + 5)   /* display detected VGA type for 5 secs */
  1026.     ;
  1027. #endif
  1028.  
  1029. #ifdef DOS386
  1030.     int86_real(0x10, &inr, &outr); /* do the BIOS video mode sel. call */
  1031. #else
  1032.     int86(0x10, &inr, &outr);   /* do the BIOS video mode sel. call */
  1033. #endif
  1034.  
  1035.     if (whichvga == MODE13x)    /* Tweak VGA registers to get higher res! */
  1036.     {
  1037.     outpw(SEQUENCER, 0x0604);   /* disable chain 4 */
  1038.     outpw(SEQUENCER, 0x0f02);   /* allow writes to all planes */
  1039. #ifdef DOS386
  1040.     fp = MK_FP(_x386_zero_base_selector, 0xA0000);
  1041. #else
  1042. #ifdef DOS16RM
  1043.     fp = display_base;
  1044. #else
  1045.     fp = MK_FP(0xA000, 0);
  1046. #endif
  1047. #endif
  1048.     for (u = 0; u < 43200; u++) /* clear the whole screen */
  1049.         {
  1050.         fp = (unsigned char *)MK_FP(0xA000, u);
  1051.         *fp = 0;                /* set all bytes to 0 */
  1052.         }
  1053.     outpw(SEQUENCER, 0x0100);   /* synchronous reset */
  1054.     outp(MISCOUT, 0xE7);        /* use 28 mhz dot clock */
  1055.     outpw(SEQUENCER, 0x0300);   /* restart sequencer */
  1056.     outp(CRTC, 0x11);           /* ctrl register 11, please */
  1057.     outp(CRTC+1, inp(CRTC+1) & 0x7f); /* write-prot cr0-7 */
  1058.  
  1059.     for (i = 0; i < 17; i++)    /* write CRTC register array */
  1060.         outpw(CRTC, vptbl[i]);
  1061.     }
  1062.  
  1063.     if (PaletteOption == HICOLOR && whichvga == TSENG4) {
  1064.     if ((int)inr.h.al == 0x78)      /* if it was mode 78 */
  1065.        inr.x.bx = 0x2F;             /* make it 2F... */
  1066.     else
  1067.        inr.x.bx = (unsigned int)inr.h.al;
  1068.     inr.x.ax = 0x10F0;
  1069.     int86(0x10, &inr, &inr); /* Go from 256 color to 32K color mode */
  1070.     r_mask = g_mask = b_mask = 0xF8;
  1071.     r_shift = 7;
  1072.     g_shift = 2;
  1073.     b_shift = 3;
  1074.     svga_yincr <<= 1;
  1075.     }
  1076.  
  1077.     if (whichvga != ATIXL && PaletteOption != HICOLOR && PaletteOption != FULLCOLOR)
  1078.     palette_init();  /* if we get here it has a normal 256 color palette DAC */
  1079.  
  1080.     if (whichvga == CHIPSTECH) {        /* (not sure why this is necessary) */
  1081.     outpw(0x46E8, 0x001E);          /* put chip in setup mode */
  1082.     outpw(0x103, 0x0080);           /* enable extended registers */
  1083.     outpw(0x46E8, 0x000E);          /* take chip out of setup mode */
  1084.     outp(0x3D6, 0x10);
  1085.     }
  1086.  
  1087. exit_point:
  1088.     if (whichvga == VESA && vesamode == 0x13) {
  1089.     svga_height = 200;
  1090.     svga_width = 320;
  1091. /*        svga_yincr = 320; */
  1092.     }
  1093.     if (screen_height <= svga_height)
  1094.     y_off = (svga_height - screen_height)/2;
  1095.     else
  1096.     Height_Adjust = (DBL)screen_height / (DBL)svga_height;
  1097.     if (screen_width <= svga_width)
  1098.     x_off = (svga_width - screen_width)/2;
  1099.     else
  1100.     Width_Adjust = (DBL)screen_width / (DBL)svga_width;
  1101.  
  1102.     box(0, 0, width-1, height-1);
  1103.  
  1104. #if defined(DOS16RM)
  1105.     for (u=0; u < 257; u++)
  1106.     answer[u] = save[u];
  1107. #endif
  1108. #ifdef _INTELC32_
  1109.     _dos_setvect(0x10, prev_int10);/* Restore previous handler */
  1110.     _dos_freemem((unsigned) answer);/* Free DOS buffer */
  1111. #endif
  1112.     return;
  1113. }
  1114.  
  1115.  
  1116. int AutodetectVGA()           /* Autodetect (S)VGA Adapter Type */
  1117.     {
  1118.     unsigned char _far *biosptr;
  1119.     unsigned char tmp_byte;
  1120.     unsigned int tmp_word;
  1121.     unsigned int retval;
  1122.     union REGS inr, outr;
  1123.     struct SREGS segs;
  1124.  
  1125. #if !defined(GCCDOS) && !defined(__386__) && !defined(_INTELC32_)
  1126. #if !defined(__ZTC__)
  1127.     if (tiga_set(CD_OPEN) >= 0) /* Try initializing HGWS/TIGA Adapter */
  1128.     {
  1129.     get_config(&config);
  1130.     vga_512K = TRUE;        /* All True-Color Adapters are > 512K! */
  1131.     if ((config.mode.disp_vres == 640) && (config.mode.disp_psize == 16) == TRUE)
  1132.         return(TIGA_16);
  1133.     if ((config.mode.disp_vres == 480) && (config.mode.disp_hres == 512) == TRUE)
  1134.         return(TIGA_24);
  1135.     if ((config.mode.disp_hres == 640) && (config.mode.disp_psize == 32) == TRUE)
  1136.         return(TRUE_640);
  1137.     if ((config.mode.disp_vres == 600) && (config.mode.disp_hres == 800) == TRUE)
  1138.         return(TRUE_800);
  1139.     return(TRUE_1024);
  1140.     }
  1141. #endif
  1142. #endif
  1143.  
  1144.     inr.x.ax = 0x4F00;                  /* Test for VESA Adapter */
  1145. #ifdef GCCDOS
  1146.     inr.x.di = di_val;                  /* deposit results here */
  1147.     int86x(0x10, &inr, &outr, &segs);
  1148. #else
  1149. #ifdef DOS386
  1150.     inr.x.di = real_buf[0];             /* deposit results here */
  1151.     segread(&segs);                     /* get our DS, etc. */
  1152.     segs.es = real_buf[1];              /* get segment of answer */
  1153.     int86x_real(0x10, &inr, &outr, &segs);
  1154.     for(tmp_word=0; tmp_word<sizeof(answer); tmp_word++)
  1155.     answer[tmp_word] = real_ptr[tmp_word];
  1156. #else
  1157. #ifdef DOS16RM
  1158.     inr.x.di = 0x580;                   /* deposit results here */
  1159.     segs.es = 0;
  1160.     int86x(0x10, &inr, &outr, &segs);
  1161. #else
  1162.     segread(&segs);                     /* get our DS, etc. */
  1163.     inr.x.di = FP_OFF(answer);      /* deposit results here */
  1164.     segread(&segs);                 /* get our DS, etc. */
  1165.     segs.es = FP_SEG(answer);       /* get segment of answer */
  1166.     int86x(0x10, &inr, &outr, &segs); /* BIOS adapter identify call */
  1167. #endif
  1168. #endif
  1169. #endif
  1170.  
  1171.     if (outr.x.ax == 0x004F && answer[0] == 'V' && answer[1] == 'E' &&
  1172.         answer[2] == 'S' && answer[3] == 'A') {
  1173.     vga_512K = TRUE;            /* assume all VESA's have >= 512K */
  1174.     return (VESA);
  1175.     }
  1176.  
  1177. #ifdef DOS386
  1178.     biosptr = MK_FP(_x386_zero_base_selector, 0x000C0040);
  1179. #else
  1180. #ifdef DOS16RM
  1181.     biosptr = (unsigned char *)D16SegAbsolute(0xC0040, 16);
  1182. #else
  1183.     biosptr = (unsigned char *)MK_FP(0xC000, 0x0040); /* Test for ATI Wonder */
  1184. #endif
  1185. #endif
  1186.  
  1187.     if (*biosptr == '3' && *(biosptr + 1) == '1')
  1188.     {
  1189.     _disable();                     /* Disable system interrupts */
  1190.     outp(0x1CE, 0xBB);
  1191.     if (inp(0x1CD) & 0x20)
  1192.         vga_512K = TRUE;
  1193.     _enable();                      /* Re-enable system interrupts */
  1194. #ifdef DOS16RM
  1195.     D16SegCancel((void *)biosptr);
  1196. #endif
  1197.     return (ATIVGA);
  1198.     }
  1199.     inr.x.ax = 0x7000;                  /* Test for Everex &| Trident */
  1200.     inr.x.bx = 0;
  1201.  
  1202.     CLD;
  1203.  
  1204.     int86(0x10, &inr, &outr);
  1205.     if (outr.h.al == 0x70)
  1206.     {
  1207.     if (outr.h.ch & 0xC0)
  1208.         vga_512K = TRUE;
  1209.     outr.x.dx &= 0xFFF0;
  1210.     if (outr.x.dx == 0x6780)
  1211.         {
  1212.         printf("\nT6780\n");
  1213.         return (TRIDENT);
  1214.         }
  1215.     if (outr.x.dx == 0x2360)
  1216.         {
  1217.         printf("\nT2360\n");
  1218.         return (TRIDENT);
  1219.         }
  1220.     if (outr.x.dx == 0x6730)        /* EVGA? (No BIOS Page Fn.) */
  1221.         {
  1222.         printf("\nE6730\n");
  1223.         return (EVEREX);
  1224.         }
  1225.     printf("\nE0000\n");
  1226.     return (EVEREX);        /* Newer board with fetchable bankswitch */
  1227.     }
  1228.     outp(0x3C4, 0x0B);                  /* Test for Trident */
  1229.     tmp_byte = (unsigned char) inp(0x3C5);
  1230.     if ((tmp_byte > 1) && (tmp_byte < 0x10))
  1231.     {
  1232.     vga_512K = TRUE;
  1233.     printf("\nT0000\n");
  1234.     return (TRIDENT);
  1235.     }
  1236.     if (cirrus())                       /* Test Video7 Vega VGA (Cirrus) */
  1237.     return (CIRRUS);
  1238.     inr.x.ax = 0x6F00;                  /* Test for Video7 SVGA */
  1239.     inr.x.bx = 0;                       /* note - Vega VGA (Cirrus) will */
  1240.  
  1241.     CLD;
  1242.  
  1243.     int86(0x10, &inr, &outr);           /* pass this test - test Cirrus 1st */
  1244.     if (outr.h.bh == 'V' && outr.h.bl == '7')
  1245.     {
  1246.     inr.x.ax = 0x6F07;
  1247.  
  1248.     CLD;
  1249.  
  1250.     int86(0x10, &inr, &outr);
  1251.     if ((outr.h.ah & 0x7F) > 1)
  1252.         vga_512K = TRUE;
  1253.     return (VIDEO7);
  1254.     }
  1255.     outp(0x3CE, 9);                     /* Test for Paradise */
  1256.     if (!inp(0x3CF))
  1257.     {
  1258.     outpw(0x3CE, 0x050F);           /* Turn off write protect on regs */
  1259.     if (chkbank(0,1))               /* if bank 0 and 1 same not para. */
  1260.         {                           /* FALSE == banks same... (C) */
  1261.         if (chkbank(0, 64))         /* if bank 0 and 64 same only 256K */
  1262.         vga_512K = TRUE;
  1263.  
  1264.         retval = PARADISE;
  1265. #ifdef DOS16RM
  1266.         biosptr = (unsigned char *)D16SegAbsolute(0xC0039, 16);
  1267.         if ((*biosptr == '1') && (*biosptr+1 == '6')) /* p/n 003116 */
  1268.         retval = VDC600;        /* a real Paradise is p/n 003145 */
  1269.         D16SegCancel((void *)biosptr);
  1270. #else
  1271.         biosptr = (unsigned char *)MK_FP(0xC000, 0x0039);/* Test for AT&T VDC600 */
  1272.         if ((*biosptr == '1') && (*biosptr+1 == '6')) /* p/n 003116 */
  1273.         retval = VDC600;        /* a real Paradise is p/n 003145 */
  1274. #endif
  1275.         return (retval);
  1276.         }
  1277.     }
  1278.     inr.x.ax = 0x5F00;                  /* Test for Chips & Tech */
  1279.     inr.x.bx = 0;
  1280.  
  1281.     CLD;
  1282.  
  1283.     int86(0x10, &inr, &outr);
  1284.     if (outr.h.al == 0x5F)
  1285.     {
  1286.     if (outr.h.bh >= 1)
  1287.         vga_512K = TRUE;
  1288.     return (CHIPSTECH);
  1289.     }
  1290.     outp(0x3D4, 0x33);                  /* Test for Tseng 4000 or 3000 Chip */
  1291.     tmp_word = (unsigned int) inp(0x3D5) << 8;
  1292.     outpw(0x3D4, 0x0A33);
  1293.     outp(0x3D4, 0x33);
  1294.     retval = BASIC_VGA;
  1295.     if ((inp(0x3D5) & 0x0F) == 0x0A)
  1296.     {
  1297.     outpw(0x3D4, 0x0533);
  1298.     outp(0x3D4, 0x33);
  1299.     if ((inp(0x3D5) & 0x0F) == 0x05)
  1300.         {
  1301.         retval = TSENG4;
  1302.         outpw(0x3D4, tmp_word | 0x33);
  1303.         outp(0x3D4, 0x37);
  1304.         if ((inp(0x3D5) & 0x0A) == 0x0A)
  1305.         vga_512K = TRUE;
  1306.         outp(0x3BF, 0x03);          /* Enable access to extended regs */
  1307.         outp(0x3D8, 0xA0);
  1308.         outp(0x3D8, 0x29);          /* Enable mapping register access */
  1309.         outp(0x3D8, 0xA0);
  1310.         }
  1311.     }
  1312.     tmp_byte = (unsigned char) inp(0x3CD);      /* save bank switch reg */
  1313.     outp(0x3CD, 0xAA);                          /* test register w/ 0xAA */
  1314.     if (inp(0x3CD) == 0xAA)
  1315.     {
  1316.     outp(0x3CD, 0x55);                      /* test register w/ 0x55 */
  1317.     if (inp(0x3CD) == 0x55)
  1318.         {
  1319.         outp(0x3CD, tmp_byte);              /* restore bank switch reg */
  1320.         if (retval != TSENG4)             /* yep, it's a Tseng... */
  1321.         retval = TSENG3;
  1322.         vga_512K = TRUE;
  1323.         return (retval);
  1324.         }
  1325.     }
  1326.     outpw(0x3CE, 0x200F);               /* Test for Ahead A or B chipsets */
  1327.     tmp_byte = (unsigned char) inp(0x3CF);
  1328.     if (tmp_byte == 0x21)
  1329.     {
  1330.     vga_512K = TRUE;                /* Assume all Ahead's have 512K... */
  1331.     return (AHEADB);
  1332.     }
  1333.     if (tmp_byte == 0x20)
  1334.     {
  1335.     vga_512K = TRUE;
  1336.     return (AHEADA);
  1337.     }
  1338.     if ((inp(0x3DE) & 0xE0) == 0x60)    /* Test for Oak Tech OTI-067 */
  1339.     {
  1340.     outp(0x3DE, 0x0D);
  1341.     if (inp(0x3DF) & 0x80)
  1342.         vga_512K = TRUE;
  1343.     return(OAKTECH);
  1344.     }
  1345.     return (BASIC_VGA);                 /* Return 1 if Unknown/BASIC_VGA */
  1346.     }
  1347.  
  1348. int cirrus()                    /* Test for presence of Cirrus VGA Chip */
  1349.     {
  1350.     unsigned char tmp_byte;
  1351.     unsigned int crc_word, tmp_word;
  1352.     int retcode = FALSE;
  1353.  
  1354.     outp(0x3D4, 0x0C);  /* assume 3Dx addressing, scrn A start addr hi */
  1355.     crc_word = (unsigned int) inp(0x3D5) << 8;  /* save the crc */
  1356.     outp(0x3D5, 0);                             /* clear the crc */
  1357.     outp(0x3D4, 0x1F);                          /* Eagle ID register */
  1358.     tmp_byte = (unsigned char) inp(0x3D5);      /* nybble swap "register" */
  1359.     tmp_word = (((tmp_byte & 0x0F) << 4) | ((tmp_byte & 0xf0) >> 4)) << 8;
  1360.     outpw(0x3C4, tmp_word | 0x06);              /* disable extensions */
  1361.     if (!inp(0x3C5))
  1362.     {
  1363.     tmp_word = (unsigned int) tmp_byte << 8;
  1364.     outpw(0x3C4, tmp_word | 0x06);          /* re-enable extensions */
  1365.     if (inp(0x3C5) == 1)
  1366.         retcode = TRUE;
  1367.     }
  1368.     outpw(0x3D5, crc_word | 0x0c);              /* restore the crc */
  1369.     return (retcode);
  1370.     }
  1371.  
  1372. int chkbank(bank0, bank1)       /* Paradise SVGA specific stuff */
  1373.    unsigned int bank0, bank1;   /* returns TRUE if banks are different RAM */
  1374.    {
  1375.    static unsigned int value = 0x1234;
  1376.    unsigned int _far *fp;
  1377.    unsigned int temp;
  1378.    unsigned int oldval0, oldval1;
  1379.  
  1380. #ifdef DOS386                           /* point out into display RAM */
  1381.    fp = MK_FP(_x386_zero_base_selector, 0xB8000);
  1382. #else
  1383.    fp = (unsigned int *)MK_FP(0xB800, 0); /* point out into display RAM */
  1384. #endif
  1385.  
  1386.    outp(0x3CE, 9);
  1387.    outp(0x3CF, bank0);  /* save prior video data and write test values */
  1388.    oldval0 = *fp;
  1389.    *fp ^= value;
  1390.    if (*fp != (oldval0 ^ value)) {
  1391.       *fp = oldval0;
  1392.       return FALSE;             /* No RAM there at all -- can't be 512K */
  1393.       }
  1394.  
  1395.    outp(0x3CE, 9);
  1396.    outp(0x3CF, bank1);  /* save prior video data and write test values */
  1397.    oldval1 = *fp;
  1398.    *fp ^= value;
  1399.    if (*fp != (oldval1 ^ value)) {
  1400.       *fp = oldval1;
  1401.       outp(0x3CE, 9);
  1402.       outp(0x3CF, bank0);
  1403.       *fp = oldval0;
  1404.       return FALSE;             /* No RAM there at all -- can't be 512K */
  1405.       }
  1406.    if (*fp != oldval0) {
  1407.       *fp = oldval1;
  1408.       outp(0x3CE, 9);
  1409.       outp(0x3CF, bank0);
  1410.       *fp = oldval0;
  1411.       return TRUE;              /* pages cannot be the same RAM */
  1412.       }
  1413.  
  1414.    outp(0x3CE, 9);
  1415.    outp(0x3CF, bank0);
  1416.    temp = *fp;
  1417.    outp(0x3CE, 9);
  1418.    outp(0x3CF, bank1);
  1419.    *fp = oldval1;
  1420.    outp(0x3CE, 9);
  1421.    outp(0x3CF, bank0);
  1422.    *fp = oldval0;
  1423.  
  1424.    if (temp == oldval0)
  1425.       return FALSE;             /* pages are the same RAM */
  1426.    else
  1427.       return TRUE;              /* independent values, so not same RAM */
  1428.    }
  1429.  
  1430. /* BP ? */   
  1431. void atiplot(x, y, r, g, b)     /* ATI VGA Wonder XL 32K color display plot */
  1432. int x, y, r, g, b;
  1433. {
  1434.    char plane=0;
  1435.    unsigned offset;
  1436.    unsigned long address;
  1437.    unsigned short _far *fp;
  1438.  
  1439.    r/=8;
  1440.    g/=8;
  1441.    b/=8;
  1442.    address = y * 1280L + x * 2L;
  1443.    offset = (unsigned)(address % 65536L);
  1444.    plane = (char)(address / 65536L);
  1445.    _disable();
  1446.    atibank(plane);
  1447.  
  1448. #ifdef DOS386
  1449.    fp = MK_FP(_x386_zero_base_selector, 0xA0000 + offset);
  1450. #else
  1451. #ifdef DOS16RM
  1452.    fp = (unsigned short *)(display_base + offset);
  1453. #else
  1454.    fp = (unsigned short *)MK_FP(0xA000, offset);
  1455. #endif
  1456. #endif
  1457.  
  1458.    *fp = (unsigned short)(r * 1024 + g * 32 + b);
  1459.    _enable();
  1460.    return;
  1461. }
  1462.  
  1463. void atibank(b)         /* ATI VGA Wonder XL bank switch routine */
  1464. int b;
  1465. {
  1466.    unsigned tmp_word;
  1467.    outp(0x1CE, 0xB2);
  1468.    tmp_word = (unsigned int)((b << 1) | (inp(0x1CF) & 0xE1));
  1469.    outpw(0x1CE, (tmp_word << 8) | 0x00B2);
  1470.    return;
  1471. }
  1472.  
  1473.  
  1474. void palette_init()             /* Fill VGA 256 color palette with colors! */
  1475.     {
  1476.     register unsigned m;
  1477.     unsigned r, g, b;
  1478.     register DBL hue, sat, val;
  1479.  
  1480.     if (PaletteOption == GREY)  /* B/W Video Mod */
  1481.     {
  1482.     for (m = 1; m < 64; m++)     /* for the 1st 64 colors... */
  1483.         set_palette_register (m, m, m, m); /* set m to rgb value */
  1484.     for (m = 64; m < 256; m++)     /* for the remaining, at full value */
  1485.         set_palette_register (m, 63, 63, 63);
  1486.     return;
  1487.     }
  1488.     if (PaletteOption == P_332) /* 332 Video Mod */
  1489.     {
  1490.         for (r=0;r<8;r++)
  1491.             for (g=0;g<8;g++)
  1492.                 for (b=0;b<4;b++) {
  1493.                     m = (r * 32 + g * 4 + b);
  1494.                     set_palette_register(m, r * 9, g * 9, b * 21);
  1495.                 }
  1496.         return;
  1497.     }
  1498.     set_palette_register(0, 0, 0, 0);   /* make palette register 0 black */
  1499.  
  1500.     set_palette_register(64, 63, 63, 63); /* make palette register 64 white */
  1501.  
  1502.     set_palette_register(128, 31, 31, 31); /* make register 128 dark grey */
  1503.  
  1504.     set_palette_register(192, 48, 48, 48); /* make register 192 lite grey */
  1505.  
  1506.     for (m = 1; m < 64; m++)     /* for the 1st 64 colors... */
  1507.     {
  1508.     sat = 0.5;      /* start with the saturation and intensity low */
  1509.     val = 0.5;
  1510.     hue = 360.0 * ((DBL)(m)) / 64.0;   /* normalize to 360 */
  1511.     hsv_to_rgb (hue, sat, val, &r, &g, &b);
  1512.     set_palette_register (m, r, g, b); /* set m to rgb value */
  1513.  
  1514.     sat = 1.0;      /* high saturation and half intensity (shades) */
  1515.     val = 0.50;
  1516.     hue = 360.0 * ((DBL)(m)) / 64.0;   /* normalize to 360 */
  1517.     hsv_to_rgb (hue, sat, val, &r, &g, &b);
  1518.     set_palette_register (m + 64, r, g, b);  /* set m + 64 */
  1519.  
  1520.     sat = 0.5;      /* half saturation and high intensity (pastels) */
  1521.     val = 1.0;
  1522.  
  1523.     hue = 360.0 * ((DBL)(m)) / 64.0;   /* normalize to 360 */
  1524.     hsv_to_rgb (hue, sat, val, &r, &g, &b);
  1525.     set_palette_register (m + 128, r, g, b); /* set m + 128 */
  1526.  
  1527.     sat = 1.0;            /* normal full HSV set at full intensity */
  1528.     val = 1.0;
  1529.    
  1530.     hue = 360.0 * ((DBL)(m)) / 64.0;   /* normalize to 360 */
  1531.     hsv_to_rgb (hue, sat, val, &r, &g, &b);
  1532.     set_palette_register (m + 192, r, g, b); /* set m + 192 */
  1533.     }
  1534.     return;
  1535.     }
  1536.  
  1537.  
  1538. void display_finished ()
  1539.     {
  1540.     if (Options & PROMPTEXIT)
  1541.     {
  1542.     printf ("\007\007");    /* long beep */
  1543.     while(!kbhit())         /* wait for key hit */
  1544.        ;
  1545.     if (!getch())           /* get another if ext. scancode */
  1546.        getch();
  1547.     }
  1548.     }
  1549.  
  1550.  
  1551. void display_close()   /* setup to Text 80x25 (mode 3) */
  1552.     {
  1553.     union REGS regs;
  1554. #ifdef __386__
  1555.     struct SREGS segs;
  1556.  
  1557.     regs.x.ax = 0x0003;
  1558.     int86(0x10, ®s, ®s);
  1559.     regs.x.ax = 0x4900;
  1560.     segs.es = vesabuffer;
  1561.     segs.ds = 0;
  1562.     int86x(0x21, ®s, ®s, &segs);
  1563. #else
  1564. #if defined(_INTELC32_) || defined(GCCDOS) || defined(DOS16RM) || defined(DOS386)
  1565.     regs.x.ax = 0x0003;
  1566.     int86(0x10, ®s, ®s);
  1567. #else
  1568.     if (whichvga < TRUECOLOR) {
  1569.     regs.x.ax = 0x0003;
  1570.     int86(0x10, ®s, ®s);
  1571.     }
  1572.     else
  1573.     set_videomode(PREVIOUS, INIT);
  1574. #endif
  1575. #endif
  1576.  
  1577. #ifdef DOS16RM
  1578.     D16SegCancel(display_base);
  1579. #endif
  1580.     return;
  1581.     }
  1582.  
  1583.  
  1584.   /* plot a single RGB pixel */
  1585. #ifdef ANSIFUNC
  1586. void display_plot (                     /* plot a single RGB pixel */
  1587.    int x, int y,
  1588.    unsigned char Red,
  1589.    unsigned char Green,
  1590.    unsigned char Blue)
  1591. #else
  1592. void display_plot (x, y, Red, Green, Blue)   /* plot a single RGB pixel */
  1593.    int x, y;
  1594.    unsigned Red, Green, Blue;
  1595. #endif
  1596.    {
  1597.    union REGS inr;
  1598.    register unsigned char color, svga_page;
  1599.    unsigned char _far *fp;
  1600.    unsigned int svga_word;
  1601.    unsigned long svga_loc;
  1602.    DBL h, s, v, fx, fy;
  1603. #ifdef DITHERED
  1604.    int i, r, g, b, re, ge, be, ri, gi, bi;
  1605. #endif
  1606.  
  1607.    if (x == 0)                  /* first pixel on this line? */
  1608.     {
  1609. #ifdef DITHERED
  1610.     for(i=0;i<screen_width+2;i++)
  1611.         {
  1612.         r_err[(y+1)&1][i+x_off] = 0;
  1613.         g_err[(y+1)&1][i+x_off] = 0;
  1614.         b_err[(y+1)&1][i+x_off] = 0;
  1615.         }
  1616. #endif          
  1617.     lastx = -1;             /* reset cache, make sure we do the 1st one */
  1618.     lasty = lastline;       /* set last line do to prior line */
  1619.     }
  1620.  
  1621.     y += y_off;
  1622.     x += x_off;
  1623.    
  1624.    /* Scaling factors precomputed per RHA in Height_Adjust or Width_Adjust */
  1625.     
  1626.    if (screen_height > svga_height)     /* auto-scale Y */
  1627.     {
  1628.     fy = (DBL)y / Height_Adjust;
  1629.     y = (int)fy;            /* scale y to svga_height */
  1630.     if (y <= lasty)         /* discard if repeated line */
  1631.         return;
  1632.     lastline = y;           /* save current working line */
  1633.     }
  1634.  
  1635.    if (screen_width > svga_width)               /* auto-scale X */
  1636.     {
  1637.     fx = (DBL)x / Width_Adjust;
  1638.     x = (int)fx;            /* scale x to svga_width */
  1639.     if (x <= lastx)         /* discard if repeated pixel */
  1640.         return;
  1641.     lastx = x;              /* save most recent pixel done */
  1642.     }
  1643.  
  1644.    if (whichvga == ATIXL)
  1645.     {
  1646.     atiplot(x, y, Red, Green, Blue);
  1647.     return;
  1648.     }
  1649.     
  1650. #if !defined(_INTELC32_) && !defined(__386__) && !defined(GCCDOS)
  1651. #if !defined(__ZTC__)
  1652.    if (whichvga == TIGA_16)
  1653.     {
  1654.     set_bcolor(0);
  1655.     set_fcolor(((unsigned)Red << 10) + (Green << 5) + Blue);
  1656.     draw_point(x, y);
  1657.     return;
  1658.     }
  1659.  
  1660.    if (whichvga == TIGA_24 || whichvga == TRUE_640 || whichvga == TRUE_640 || whichvga == TRUE_1024)
  1661.     {
  1662.     hpt[0] = Green;
  1663.     hpt[1] = Red;
  1664.     hpt[2] = Blue;
  1665.     host2gsp(hptr, ((whichvga == TIGA_24) ? 0x4000L : 0x8000L) * y + ((long) x << 5), 3, 0);
  1666.     return;
  1667.     }
  1668. #endif
  1669. #endif
  1670.  
  1671.    if (PaletteOption == FULLCOLOR)
  1672.     {
  1673.     svga_loc = ((unsigned long)svga_yincr) * y + x * bpp/8;
  1674.     svga_page = (unsigned char)(svga_loc/gran);
  1675.     svga_loc %= gran;
  1676.     if (svga_page != cur_page)
  1677.         {
  1678.         cur_page = svga_page;
  1679.         if (whichvga != VESA)
  1680.         outp(0x3CD, (unsigned char)svga_page);
  1681.         else
  1682.         {
  1683.         inr.x.bx = map_code;            /* map code = 0 or 1 */
  1684.         inr.x.ax = 0x4F05;
  1685.         inr.x.dx = (unsigned int)svga_page;
  1686. #ifdef DOS386
  1687.         int86_real(0x10, &inr, &inr);
  1688. #else
  1689.         int86(0x10, &inr, &inr);
  1690. #endif
  1691.         }
  1692.         }
  1693.  
  1694. #ifdef DOS386
  1695.     fp = MK_FP(_x386_zero_base_selector, 0xA0000 + (unsigned int)svga_loc);
  1696. #else
  1697. #ifdef DOS16RM
  1698.     fp = display_base + (unsigned int)svga_loc;
  1699. #else
  1700.     fp = (unsigned char *)MK_FP(0xA000, (unsigned int)svga_loc);
  1701. #endif
  1702. #endif
  1703.     *fp++ = Blue;
  1704.     *fp++ = Green;
  1705.     *fp++ = Red;
  1706.     return;
  1707.     }
  1708.    if (PaletteOption == HICOLOR)
  1709.     {
  1710.     svga_loc = ((unsigned long)svga_yincr) * y + (x << 1);
  1711.     svga_page = (unsigned char)(svga_loc/gran);
  1712.     svga_loc %= gran;
  1713.     if (svga_page != cur_page)
  1714.         {
  1715.         cur_page = svga_page;
  1716.         if (whichvga != VESA)
  1717.         outp(0x3CD, (unsigned char)svga_page);
  1718.         else
  1719.         {
  1720.         inr.x.bx = map_code;            /* map code = 0 or 1 */
  1721.         inr.x.ax = 0x4F05;
  1722.         inr.x.dx = (unsigned int)svga_page;
  1723. #ifdef DOS386
  1724.         int86_real(0x10, &inr, &inr);
  1725. #else
  1726.         int86(0x10, &inr, &inr);
  1727. #endif
  1728.         }
  1729.         }
  1730.  
  1731. #ifdef DOS386
  1732.     fp = MK_FP(_x386_zero_base_selector, 0xA0000 + (unsigned int)svga_loc);
  1733. #else
  1734. #ifdef DOS16RM
  1735.     fp = display_base + (unsigned int)svga_loc;
  1736. #else
  1737.     fp = (unsigned char *)MK_FP(0xA000, (unsigned int)svga_loc);
  1738. #endif
  1739. #endif
  1740.  
  1741. #ifdef DITHERED
  1742.     r = (int)Red + (int)r_err[y&1][x+1];
  1743.     g = (int)Green + (int)g_err[y&1][x+1];
  1744.     b = (int)Blue + (int)b_err[y&1][x+1];
  1745.  
  1746.     ri = (r+3) >> 3;
  1747.     gi = (g+3) >> 3;
  1748.     bi = (b+3) >> 3;
  1749.  
  1750.     if(ri > 31) ri = 31;
  1751.     if(gi > 31) gi = 31;
  1752.     if(bi > 31) bi = 31;
  1753.     if(ri < 0) ri = 0;
  1754.     if(gi < 0) gi = 0;
  1755.     if(bi < 0) bi = 0;
  1756.  
  1757.     re = r - ((255*ri)/31);
  1758.     ge = g - ((255*gi)/31);
  1759.     be = b - ((255*bi)/31);
  1760.     r_err[y&1][x+2] += (signed char)((7*re)/16);
  1761.     r_err[y&1][x] += (signed char)(re/16);
  1762.     r_err[(y+1)&1][x+1] += (signed char)((5*re)/16);
  1763.     r_err[(y+1)&1][x+2] += (signed char)((3*re)/16);
  1764.     g_err[y&1][x+2] += (signed char)((7*ge)/16);
  1765.     g_err[y&1][x] += (signed char)(ge/16);
  1766.     g_err[(y+1)&1][x+1] += (signed char)((5*ge)/16);
  1767.     g_err[(y+1)&1][x+2] += (signed char)((3*ge)/16);
  1768.     b_err[y&1][x+2] += (signed char)((7*be)/16);
  1769.     b_err[y&1][x] += (signed char)(be/16);
  1770.     b_err[(y+1)&1][x+1] += (signed char)((5*be)/16);
  1771.     b_err[(y+1)&1][x+2] += (signed char)((3*be)/16);
  1772.  
  1773.     *(unsigned short _far *)fp = (unsigned short)  /* stash 16-bit pixel */
  1774.         (((unsigned long)(ri << 10)) |
  1775.         ((unsigned long)(gi << 5)) |
  1776.         ((unsigned long)(bi)));
  1777.     return;
  1778. #else
  1779.     *(unsigned short _far *)fp = (unsigned short)  /* stash 16-bit pixel */
  1780.         (((unsigned long)(Red & r_mask) << r_shift) |
  1781.         ((unsigned long)(Green & g_mask) << g_shift) |
  1782.         ((unsigned long)(Blue & b_mask) >> b_shift));
  1783.     return;
  1784. #endif
  1785.     }
  1786.  
  1787.    if (PaletteOption == GREY)           /* RGB are already set the same, so */
  1788.       color = (unsigned char)(Green >> 2);  /* really, any color will do... */
  1789.    else if (PaletteOption == P_332) {
  1790. #ifdef DITHERED
  1791.       r = (int)Red + (int)r_err[y&1][x+1];
  1792.       g = (int)Green + (int)g_err[y&1][x+1];
  1793.       b = (int)Blue + (int)b_err[y&1][x+1];
  1794.  
  1795.       ri = (r+18)/36;
  1796.       gi = (g+18)/36;
  1797.       bi = (b+42)/84;
  1798.  
  1799.       if (ri > 7)
  1800.           ri=7;
  1801.       if (gi > 7)
  1802.           gi=7;
  1803.       if (bi > 3)
  1804.           bi=3;
  1805.       if (ri < 0)
  1806.           ri=0;
  1807.       if (gi < 0)
  1808.           gi=0;
  1809.       if (bi < 0)
  1810.           bi=0;
  1811.     
  1812.       color = (unsigned char)(((ri<<5) + (gi<<2) + bi));
  1813.  
  1814.       re = r - ((255 * ri) / 7);
  1815.       ge = g - ((255 * gi) / 7);
  1816.       be = b - ((255 * bi) / 3);
  1817.  
  1818.       r_err[y&1][x+2] += (signed char)((7*re)/16);
  1819.       r_err[y&1][x] += (signed char)(re/16);
  1820.       r_err[(y+1)&1][x+1] += (signed char)((5*re)/16);
  1821.       r_err[(y+1)&1][x+2] += (signed char)((3*re)/16);
  1822.       g_err[y&1][x+2] += (signed char)((7*ge)/16);
  1823.       g_err[y&1][x] += (signed char)(ge/16);
  1824.       g_err[(y+1)&1][x+1] += (signed char)((5*ge)/16);
  1825.       g_err[(y+1)&1][x+2] += (signed char)((3*ge)/16);
  1826.       b_err[y&1][x+2] += (signed char)((7*be)/16);
  1827.       b_err[y&1][x] += (signed char)(be/16);
  1828.       b_err[(y+1)&1][x+1] += (signed char)((5*be)/16);
  1829.       b_err[(y+1)&1][x+2] += (signed char)((3*be)/16);
  1830. #else
  1831.       color = ((Red & 0xE0) | ((Green & 0xE0) >> 3) | ((Blue & 0xC0) >> 6));
  1832. #endif
  1833.       }
  1834.    else  /* Translate RGB value to nearest of 256 palette Colors (by HSV) */
  1835.    {
  1836.       rgb_to_hsv((unsigned)Red,(unsigned)Green,(unsigned)Blue, &h, &s, &v);
  1837.       if (s < 0.20)   /* black or white if no saturation of color... */
  1838.       {
  1839.      if (v < 0.25)
  1840.         color = 0;        /* black */
  1841.      else if (v > 0.8)
  1842.         color = 64;       /* white */
  1843.      else if (v > 0.5)
  1844.         color = 192;      /* lite grey */
  1845.      else
  1846.         color = 128;      /* dark grey */
  1847.       }
  1848.       else
  1849.       {
  1850.      color = (unsigned char) (64.0 * ((DBL)(h)) / 360.0);
  1851.  
  1852.      if (!color)
  1853.         color = 1;        /* avoid black, white or grey */
  1854.       
  1855.      if (color > 63)
  1856.         color = 63;       /* avoid same */
  1857.  
  1858.      if (v > 0.50)
  1859.         color |= 0x80;    /* colors 128-255 for high inten. */
  1860.  
  1861.      if (s > 0.50)        /* more than half saturated? */
  1862.         color |= 0x40;    /* color range 64-128 or 192-255 */
  1863.       }
  1864.    }
  1865.    switch (whichvga)    /* decide on (S)VGA bank switching scheme to use */
  1866.     {
  1867.        case BASIC_VGA:      /* none */
  1868.         svga_loc = svga_yincr * y + x;
  1869.         break;
  1870.  
  1871.        case MODE13x:        /* faked */
  1872.         svga_word = 1 << (x & 3);       /* form bit plane mask */
  1873.         svga_word = (svga_word << 8) | 2;
  1874.         outpw(SEQUENCER, svga_word);    /* tweak the sequencer */
  1875.         svga_loc = svga_yincr * y + (x >> 2);
  1876.         break;
  1877.  
  1878.        default:             /* actual bank switch for all SVGA cards */
  1879.         svga_loc=((unsigned long)svga_yincr) * y + x;
  1880.         svga_page=(unsigned char)(svga_loc/gran);
  1881.         svga_loc %= gran;
  1882.         if (cur_page != svga_page)      /* if not in correct bank */
  1883.         {
  1884.             cur_page = svga_page;       /* set new working bank */
  1885.             if (whichvga != VESA)
  1886.             {
  1887.             _disable();
  1888.             newbank();
  1889.             _enable();
  1890.         }
  1891.             else
  1892.             newbank();
  1893.         }
  1894.         break;
  1895.     }
  1896.  
  1897. #ifdef DOS386
  1898.    fp = MK_FP(_x386_zero_base_selector, 0xA0000 + (unsigned int)svga_loc);
  1899. #else
  1900. #ifdef DOS16RM
  1901.    fp = display_base + (unsigned int)svga_loc;
  1902. #else
  1903.    fp = (unsigned char *)MK_FP(0xA000, (unsigned int)svga_loc);
  1904. #endif
  1905. #endif
  1906.    *fp = color;         /* write normalized pixel color val to bitplane */
  1907.  
  1908.    return;
  1909.    }
  1910.  
  1911. void newbank()          /* Perform SVGA bank switch on demand - Voila! */
  1912. {
  1913.     register unsigned char tmp_byte, tmp_byte1;
  1914.     register unsigned int tmp_word;
  1915.     union REGS regs;
  1916.     static unsigned char xlateT3[] = {0x40, 0x49, 0x52, 0x5B, 0x64, 0x6D,
  1917.         0x76, 0x7F};
  1918.     static unsigned char xlateT4[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
  1919.         0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};
  1920.  
  1921.  
  1922.     switch (whichvga)
  1923.     {
  1924.     case VDC600:                    /* AT&T VDC 600 */
  1925.         tmp_byte = (unsigned char) (cur_page << 4); /* was >> 12... */
  1926.         outpw(0x03CE,0x050F);
  1927.         outp(0x03CE,0x09);
  1928.         outp(0x03CF, tmp_byte);
  1929.         break;
  1930.     case OAKTECH:                   /* Oak Technology OTI-067 */
  1931.         tmp_byte = (unsigned char)(cur_page & 0x0F);
  1932.         outp(0x3DF, (tmp_byte << 4) | tmp_byte);
  1933.         break;
  1934.     case AHEADA:                    /* Ahead Systems Ver A */
  1935.         outpw(0x3CE, 0x200F);       /* enable extended registers */
  1936.         tmp_byte = (unsigned char)(inp(0x3CC) & 0xDF);  /* bit 0 */
  1937.         if (cur_page & 1)
  1938.             tmp_byte |= 0x20;
  1939.         outp(0x3C2, tmp_byte);
  1940.         outp(0x3CF, 0);                /* bits 1, 2, 3 */
  1941.         tmp_word = (unsigned int)((cur_page >> 1 )|(inp(0x3D0) & 0xF8));
  1942.         outpw(0x3CF, tmp_word << 8);
  1943.         break;
  1944.     case AHEADB:                    /* Ahead Systems Ver B */
  1945.         outpw(0x3CE, 0x200F);       /* enable extended registers */
  1946.         tmp_word = (unsigned int)((cur_page << 4) | cur_page);
  1947.         outpw(0x3CF, (tmp_word << 8) | 0x000D);
  1948.         break;
  1949.     case EVEREX:                    /* Everex SVGA's */
  1950.         outp(0x3C4, 8);
  1951.         if (cur_page & 1)
  1952.          tmp_word = (unsigned int)(inp(0x3C5) | 0x80);
  1953.         else tmp_word = (unsigned int)(inp(0x3C5) & 0x7F);
  1954.         outpw(0x3C4, (tmp_word << 8) | 0x0008);
  1955.         tmp_byte = (unsigned char)(inp(0x3CC) & 0xDF);
  1956.         if (!(cur_page & 2))
  1957.          tmp_byte |= 0x20;
  1958.         outp(0x3C2, tmp_byte);
  1959.         break;
  1960.     case ATIVGA:                    /* ATI VGA Wonder (and the XL) */
  1961.         outp(0x1CE, 0xB2);
  1962.         tmp_word = (unsigned int)((cur_page << 1) | (inp(0x1CF) & 0xE1));
  1963.         outpw(0x1CE, (tmp_word << 8) | 0x00B2);
  1964.         break;
  1965.     case TRIDENT:
  1966.         outp(0x3CE, 6);             /* set page size to 64K */
  1967.         tmp_word = (unsigned int)(inp(0x3CF) | 4) << 8;
  1968.         outpw(0x3CE, tmp_word | 0x0006);
  1969.         outp(0x3C4, 0x0b);          /* switch to BPS mode */
  1970.         inp(0x3C5);                 /* dummy read?? */
  1971.         tmp_word = (unsigned int)(cur_page ^ 2) << 8;
  1972.         outpw(0x3C4, tmp_word | 0x000E);
  1973.         break;
  1974.     case VIDEO7:                    /* Video-7 VRAM, FastRAM SVGA cards */
  1975.         tmp_byte1 = tmp_byte = (unsigned char)(cur_page & 0x0F);
  1976.         outpw(0x3C4, 0xEA06);
  1977.         tmp_word = (unsigned int)(tmp_byte & 1) << 8;
  1978.         outpw(0x3C4, tmp_word | 0x00F9);
  1979.         tmp_byte &= 0x0C;
  1980.         tmp_word = (unsigned int)((tmp_byte >> 2) | tmp_byte) << 8;
  1981.         outpw(0x3C4, tmp_word | 0x00F6);
  1982.         tmp_word |= (inp(0x3C5) & 0xF0) << 8;
  1983.         outpw(0x3C4, tmp_word | 0x00F6);
  1984.         tmp_byte = (unsigned char)((tmp_byte1 << 4) & 0x20);
  1985.         outp(0x3C2, (inp(0x3CC) & 0xDF) | tmp_byte);
  1986.         break;
  1987.     case CHIPSTECH:                 /* Chips & Technology VGA Chip Set */
  1988.         outp(0x3D7, cur_page << 2); /* this is all that's necessary?? */
  1989.         break;
  1990.     case PARADISE:                  /* Paradise, Professional, Plus */
  1991.         outpw(0x3CE, 0x050F);       /* turn off VGA reg. write protect */
  1992.         tmp_word = (unsigned int)(cur_page << 4) << 8;
  1993.         outpw(0x3CE, tmp_word | 0x0009);
  1994.         break;
  1995.     case TSENG3:                    /* Tseng 3000 - Orchid, STB, etc. */
  1996.         outp(0x3CD, xlateT3[cur_page & 0x07]);
  1997.         break;
  1998.     case TSENG4:                    /* Tseng 4000 - Orchid PD+, etc. */
  1999.         outp(0x3CD, xlateT4[cur_page & 0x0F]);
  2000.         break;
  2001.     case VESA:                      /* VESA standard mode bank switch */
  2002.         regs.x.ax = 0x4F05;         /* VESA BIOS bank switch call */
  2003.         regs.x.dx = cur_page;
  2004.         regs.x.bx = map_code;       /* Map code 0 or 1? */
  2005. #ifdef DOS386
  2006.         int86_real(0x10, ®s, ®s);
  2007. #else
  2008.         int86(0x10, ®s, ®s);  /* Do the video BIOS interrupt */
  2009. #endif
  2010.     }
  2011.     return;
  2012. }
  2013.  
  2014. void set_palette_register (Val, Red, Green, Blue)
  2015.    unsigned Val;
  2016.    unsigned Red, Green, Blue;
  2017.    {
  2018.    union REGS Regs;
  2019.  
  2020.    Regs.x.ax = 0x1010;              /* Set one palette register function */
  2021.    Regs.x.bx = Val;                 /* the palette register to set (color#)*/
  2022.    Regs.h.dh = (char)(Red & 0x3f);  /* set the gun values (6 bits ea.) */
  2023.    Regs.h.ch = (char)(Green & 0x3f);
  2024.    Regs.h.cl = (char)(Blue & 0x3f);
  2025.    int86(0x10, &Regs, &Regs);       /* Do the video interrupt */
  2026.    }
  2027.  
  2028. /* Conversion from Hue, Saturation, Value to Red, Green, and Blue and back */
  2029. /* From "Computer Graphics", Donald Hearn & M. Pauline Baker, p. 304 */
  2030.  
  2031. void hsv_to_rgb(hue, s, v, r, g, b)
  2032.    DBL hue, s, v;               /* hue (0.0-360.0) s and v from 0.0-1.0) */
  2033.    unsigned *r, *g, *b;         /* values from 0 to 63 */
  2034.    {
  2035.    register DBL i, f, p1, p2, p3;
  2036.    register DBL xh;
  2037.    register DBL nr, ng, nb;     /* rgb values of 0.0 - 1.0 */
  2038.  
  2039.    if (hue == 360.0)
  2040.       hue = 0.0;                /* (THIS LOOKS BACKWARDS BUT OK) */
  2041.  
  2042.    xh = hue / 60.0;             /* convert hue to be in 0,6     */
  2043.    i = floor(xh);               /* i = greatest integer <= h    */
  2044.    f = xh - i;                  /* f = fractional part of h     */
  2045.    p1 = v * (1 - s);
  2046.    p2 = v * (1 - (s * f));
  2047.    p3 = v * (1 - (s * (1 - f)));
  2048.  
  2049.    switch ((int) i)
  2050.       {
  2051.       case 0:
  2052.      nr = v;
  2053.      ng = p3;
  2054.      nb = p1;
  2055.      break;
  2056.       case 1:
  2057.      nr = p2;
  2058.      ng = v;
  2059.      nb = p1;
  2060.      break;
  2061.       case 2:
  2062.      nr = p1;
  2063.      ng = v;
  2064.      nb = p3;
  2065.      break;
  2066.       case 3:
  2067.      nr = p1;
  2068.      ng = p2;
  2069.      nb = v;
  2070.      break;
  2071.       case 4:
  2072.      nr = p3;
  2073.      ng = p1;
  2074.      nb = v;
  2075.      break;
  2076.       case 5:
  2077.      nr = v;
  2078.      ng = p1;
  2079.      nb = p2;
  2080.      break;
  2081.       default:
  2082.      nr = ng = nb = 0;
  2083.     }
  2084.  
  2085.    *r = (unsigned)(nr * 63.0); /* Normalize the values to 63 */
  2086.    *g = (unsigned)(ng * 63.0);
  2087.    *b = (unsigned)(nb * 63.0);
  2088.    
  2089.    return;
  2090.    }
  2091.  
  2092.  
  2093. void rgb_to_hsv(r, g, b, h, s, v)
  2094.    unsigned r, g, b;
  2095.    DBL *h, *s, *v;
  2096.    {
  2097.    register DBL m, r1, g1, b1;
  2098.    register DBL nr, ng, nb;             /* rgb values of 0.0 - 1.0 */
  2099.    register DBL nh = 0.0, ns, nv;       /* hsv local values */
  2100.  
  2101.    nr = (DBL) r / 255.0;
  2102.    ng = (DBL) g / 255.0;
  2103.    nb = (DBL) b / 255.0;
  2104.  
  2105.    nv = max (nr, max (ng, nb));
  2106.    m = min (nr, min (ng, nb));
  2107.  
  2108.    if (nv != 0.0)                /* if no value, it's black! */
  2109.       ns = (nv - m) / nv;
  2110.    else
  2111.       ns = 0.0;                  /* black = no colour saturation */
  2112.  
  2113.    if (ns == 0.0)                /* hue undefined if no saturation */
  2114.    {
  2115.       *h = 0.0;                  /* return black level (?) */
  2116.       *s = 0.0;
  2117.       *v = nv;
  2118.       return;
  2119.    }
  2120.  
  2121.    r1 = (nv - nr) / (nv - m);    /* distance of color from red   */
  2122.    g1 = (nv - ng) / (nv - m);    /* distance of color from green */
  2123.    b1 = (nv - nb) / (nv - m);    /* distance of color from blue  */
  2124.  
  2125.    if (nv == nr)
  2126.    {
  2127.       if (m == ng)
  2128.      nh = 5. + b1;
  2129.       else
  2130.      nh = 1. - g1;
  2131.    } 
  2132.  
  2133.    if (nv == ng)
  2134.       {
  2135.       if (m == nb)
  2136.      nh = 1. + r1;
  2137.       else
  2138.      nh = 3. - b1;
  2139.       }
  2140.  
  2141.    if (nv == nb)
  2142.       {
  2143.       if (m == nr)
  2144.      nh = 3. + g1;
  2145.       else
  2146.      nh = 5. - r1;
  2147.       }
  2148.  
  2149.    *h = nh * 60.0;      /* return h converted to degrees */
  2150.    *s = ns;
  2151.    *v = nv;
  2152.    return;
  2153.    }
  2154.  
  2155. void box(x1, y1, x2, y2)  /* RHA's draw a thin white box funct. */
  2156. int x1, y1, x2, y2;
  2157. {
  2158.    int i;
  2159.    for (i = x1+1; i < x2; i++)
  2160.    {
  2161.     display_plot(i, y1, 255, 255, 255);
  2162.     display_plot(i, y2, 255, 255, 255);
  2163.    }
  2164.    for (i = y1; i <= y2; i++)
  2165.    {
  2166.     display_plot(x1, i, 255, 255, 255);
  2167.     display_plot(x2, i, 255, 255, 255);
  2168.    }
  2169.    return;
  2170. }
  2171.  
  2172. #if !__STDC__
  2173.  
  2174. /* ANSI Standard psuedo-random number generator */
  2175.  
  2176. static unsigned long int next = 1;
  2177.  
  2178. int rand()
  2179.    {
  2180.    next = next * 1103515245L + 12345L;
  2181.    return ((int) (next / 0x10000L) & 0x7FFF);
  2182.    }
  2183.  
  2184. void srand(seed)
  2185.    unsigned int seed;
  2186.    {
  2187.    next = seed;
  2188.    }
  2189.  
  2190. #endif
  2191.  
  2192.  
  2193. /* Math Error exception struct format:
  2194.     int type;               - exception type - see below
  2195.     char _far *name;        - name of function where error occured
  2196.     long double arg1;       - first argument to function
  2197.     long double arg2;       - second argument (if any) to function
  2198.     long double retval;     - value to be returned by function
  2199. */
  2200.  
  2201. #ifdef __WATCOMC__
  2202. #define EDOM    7       /* MSC is 33 */
  2203. #define ERANGE  8       /* MSC is 34 */
  2204.  
  2205. int matherr(e)
  2206.    struct exception *e;
  2207. #else
  2208. #ifdef GCCDOS
  2209. int matherr(e)
  2210.    struct libm_exception *e;
  2211. #else
  2212. int _cdecl matherr(e)
  2213.    struct exception *e;
  2214. #endif
  2215. #endif
  2216.    {
  2217.    if (Options & DEBUGGING) {
  2218.       /* Since we are just making pictures, not keeping nuclear power under
  2219.      control - it really isn't important if there is a minor math problem.
  2220.      This routine traps and ignores them.  Note: the most common one is
  2221.      a DOMAIN error coming out of "acos". */
  2222.       switch (e->type) {
  2223.      case DOMAIN   : printf("DOMAIN error in '%s'\n", e->name); break;
  2224.      case SING     : printf("SING   error in '%s'\n", e->name); break;
  2225.      case OVERFLOW : printf("OVERFLOW error in '%s'\n", e->name); break;
  2226.      case UNDERFLOW: printf("UNDERFLOW error in '%s'\n", e->name); break;
  2227.      case TLOSS    : printf("TLOSS error in '%s'\n", e->name); break;
  2228.      case PLOSS    : printf("PLOSS error in '%s'\n", e->name); break;
  2229. #ifdef EDOM
  2230.      case EDOM     : printf("EDOM error in '%s'\n", e->name); break;
  2231. #endif
  2232. #ifdef ERANGE
  2233.      case ERANGE   : printf("ERANGE error in '%s'\n", e->name); break;
  2234. #endif
  2235.      default       : printf("Unknown math error in '%s'\n",e->name);break;
  2236.      }
  2237.       }
  2238.    return (1);  /* Indicate the math error was corrected... */
  2239.    }
  2240.  
  2241. #ifdef GCCDOS
  2242. unsigned char *find_go32(go32_offset)
  2243.    int *go32_offset;
  2244.    {
  2245.    static unsigned char *memptr = (unsigned char *)0xE0000000;
  2246.    static unsigned char buf[0x1000];
  2247.  
  2248.    union REGS reg;
  2249.    unsigned char *p;
  2250.  
  2251.    reg.x.si = (int)buf;
  2252.    reg.h.ah = 0x47;
  2253.    int86(0x21, ®, ®);
  2254.  
  2255.    for (p = &memptr[0xA0000-1-strlen((char *)buf)]; p != memptr; p--)
  2256.       if (buf[0] == *p && strcmp((char *)buf, (char *)p) == 0)
  2257.      break;
  2258.  
  2259.    if (p == memptr) {
  2260.       printf("Unable to locate the GO32 communication buffer, fatal error!\n");
  2261.       exit(1);
  2262.       }
  2263.  
  2264.    reg.h.ah = 0x1A;
  2265.    reg.x.dx = (int)buf;
  2266.    int86(0x21, ®, ®);
  2267.  
  2268.    reg.h.ah = 0x4E;
  2269.    reg.x.dx = (int)"*.*";
  2270.    int86(0x21, ®, ®);
  2271.    *go32_offset = (reg.x.dx & 0xFFFF) - 43;
  2272.  
  2273.    return(p);
  2274.    }
  2275. #endif
  2276.  
  2277. #ifdef _INTELC32_
  2278.  
  2279. void int10 ( void )         /* User Int 10h Protected-Mode Interrupt Handler */
  2280.    {
  2281.    _XSTACK *ebp;            /* Stack frame passed to real-mode handler */
  2282.    _XSTACK *ebx;            /* Stack frame returned to interrupted process */
  2283.  
  2284.    ebp = (_XSTACK *) _get_stk_frame(); /* Get stack frame address */
  2285.    if ((ebp->eax & 0x0000FFFE) != 0x4F00) { /* Check for function = 4F00/1h */
  2286.       (*prev_int10)();             /* Call previous handler? */
  2287.       return;
  2288.       }
  2289.  
  2290.    if ((ebp->edi & 0xFFF00000) != 0) {
  2291.       ebx = (_XSTACK *) _get_ebx();/* Get return stack frame address */
  2292.       ebx->eax = 0x0000104F;       /* Return code of 0x10=Extended mem err */
  2293.       ebp->flg |= _FLAG_CARRY;     /* Set carry flag to indicate an error */
  2294.       ebp->opts |= _STK_NOINT;     /* Bypass real-mode handler */
  2295.       return;
  2296.       }
  2297.  
  2298.    /* Put the segment value from the physical address in the ES.  */
  2299.    ebp->es = (short)((ebp->edi & 0x000FFFF0) >> 4);
  2300.    ebp->edi &= 0x0000000F;         /* Offset value from physical address */
  2301.    ebp->opts = 0;                  /* Pass to real-mode handler */
  2302.    return;
  2303.    }
  2304.  
  2305. #endif
  2306.  
  2307. void print_ibm_credits()
  2308.   {
  2309.   fprintf (stderr," \n");
  2310.   
  2311.   fprintf (stderr,"╔════════════════════════════════════════════════════════════════════════╗\n");
  2312.   box_fprintf (stderr,"  Persistence of Vision Raytracer Ver 1.0%s",COMPILER_VER);
  2313.   fprintf (stderr,"║────────────────────────────────────────────────────────────────────────║\n");
  2314.   fprintf (stderr,"║  Copyright (c) 1992 POV-Team                                           ║\n");
  2315.   fprintf (stderr,"║  POV-Ray is based on DKBTrace 2.12 by David K. Buck & Aaron A. Collins.║\n");
  2316.   fprintf (stderr,"║────────────────────────────────────────────────────────────────────────║\n");
  2317.   fprintf (stderr,"║  Contributing Authors: (Alphabetically)                                ║\n");
  2318.   fprintf (stderr,"║────────────────────────────────────────────────────────────────────────║\n");
  2319.   fprintf (stderr,"║  Steve A. Bennett   David K. Buck      Aaron A. Collins                ║\n");
  2320.   fprintf (stderr,"║  Alexander Enzmann  Dan Farmer         Girish T. Hagan                 ║\n");
  2321.   fprintf (stderr,"║  Douglas Muir       Bill Pulver        Robert Skinner                  ║\n");
  2322.   fprintf (stderr,"║  Scott Taylor       Drew Wells         Chris Young                     ║\n");
  2323.   fprintf (stderr,"║  -Other contributors listed in the documentation.-                     ║\n");
  2324.   fprintf (stderr,"╚════════════════════════════════════════════════════════════════════════╝\n");
  2325.   
  2326.   }  
  2327.  
  2328. /* Stats kept by the ray tracer: */
  2329. extern long Number_Of_Pixels, Number_Of_Rays, Number_Of_Pixels_Supersampled;
  2330. extern long Ray_Sphere_Tests, Ray_Sphere_Tests_Succeeded;
  2331. extern long Ray_Box_Tests, Ray_Box_Tests_Succeeded;
  2332. extern long Ray_Blob_Tests, Ray_Blob_Tests_Succeeded;
  2333. extern long Ray_Plane_Tests, Ray_Plane_Tests_Succeeded;
  2334. extern long Ray_Triangle_Tests, Ray_Triangle_Tests_Succeeded;
  2335. extern long Ray_Quadric_Tests, Ray_Quadric_Tests_Succeeded;
  2336. extern long Ray_Poly_Tests, Ray_Poly_Tests_Succeeded;
  2337. extern long Ray_Bicubic_Tests, Ray_Bicubic_Tests_Succeeded;
  2338. extern long Ray_Ht_Field_Tests, Ray_Ht_Field_Tests_Succeeded;
  2339. extern long Ray_Ht_Field_Box_Tests, Ray_HField_Box_Tests_Succeeded;
  2340. extern long Bounding_Region_Tests, Bounding_Region_Tests_Succeeded;
  2341. extern long Clipping_Region_Tests, Clipping_Region_Tests_Succeeded;
  2342. extern long Calls_To_Noise, Calls_To_DNoise;
  2343. extern long Shadow_Ray_Tests, Shadow_Rays_Succeeded;
  2344. extern long Reflected_Rays_Traced, Refracted_Rays_Traced;
  2345. extern long Transmitted_Rays_Traced;
  2346. extern time_t tstart, tstop;
  2347. extern DBL    tused;             /* Trace timer variables. - BP */ 
  2348. extern FRAME Frame;
  2349.  
  2350. extern char Input_File_Name[FILE_NAME_LENGTH], Output_File_Name[FILE_NAME_LENGTH], Stat_File_Name[FILE_NAME_LENGTH];
  2351.  
  2352. void print_ibm_stats()
  2353.    {
  2354.    int hours,min;
  2355.    DBL sec;
  2356.    FILE *stat_out;
  2357.    long Pixels_In_Image;
  2358.    
  2359.    if (Options & VERBOSE_FILE)
  2360.       stat_out = fopen(Stat_File_Name,"w+t");
  2361.    else
  2362.     stat_out = stdout;  
  2363.  
  2364.    Pixels_In_Image = (long)Frame.Screen_Width * (long)Frame.Screen_Height;
  2365.    
  2366.    fprintf (stat_out,"\n");
  2367.    fprintf (stat_out,"╔════════════════════════════════════════════════════════════════════════╗\n");
  2368.    box_fprintf (stat_out,"  Persistence of Vision Raytracer Ver 1.0%s",COMPILER_VER);
  2369.    fprintf (stat_out,"║────────────────────────────────────────────────────────────────────────║\n");
  2370.    box_fprintf (stat_out,"  %s statistics",Input_File_Name);
  2371.    if(Pixels_In_Image > Number_Of_Pixels)
  2372.    box_fprintf (stat_out,"  Partial Image Rendered");
  2373.    fprintf (stat_out,"║────────────────────────────────────────────────────────────────────────║\n");
  2374.    box_fprintf (stat_out," Image Resolution %d pixels wide x %d pixels high",Frame.Screen_Width, Frame.Screen_Height);
  2375.    box_fprintf (stat_out," # Rays Calculated     :  %10ld",Number_Of_Rays);
  2376.    box_fprintf (stat_out," # Pixels Calculated   :  %10ld", Number_Of_Pixels);
  2377.    box_fprintf (stat_out," # Pixels Supersampled :  %10ld",Number_Of_Pixels_Supersampled);
  2378.    fprintf (stat_out,"║────────────────────────────────────────────────────────────────────────║\n");
  2379.    box_fprintf (stat_out,"   Ray -» Shape Intersection Tests");
  2380.    box_fprintf (stat_out,"   Type             Tests    Succeeded   Percentage");
  2381.    fprintf (stat_out,"║────────────────────────────────────────────────────────────────────────║\n");
  2382.    if(Ray_Sphere_Tests)
  2383.    box_fprintf (stat_out,"  Sphere       %10ld  %10ld  %10.2f", Ray_Sphere_Tests, Ray_Sphere_Tests_Succeeded, ( ((DBL)Ray_Sphere_Tests_Succeeded/(DBL)Ray_Sphere_Tests) *100.0 ) );
  2384.    if(Ray_Plane_Tests)
  2385.    box_fprintf (stat_out,"  Plane        %10ld  %10ld  %10.2f", Ray_Plane_Tests, Ray_Plane_Tests_Succeeded, ( ((DBL)Ray_Plane_Tests_Succeeded/(DBL)Ray_Plane_Tests) *100.0 ));
  2386.    if(Ray_Triangle_Tests)
  2387.    box_fprintf (stat_out,"  Triangle     %10ld  %10ld  %10.2f", Ray_Triangle_Tests, Ray_Triangle_Tests_Succeeded, ( ((DBL)Ray_Triangle_Tests_Succeeded/(DBL)Ray_Triangle_Tests) *100.0 ));
  2388.    if(Ray_Quadric_Tests)
  2389.    box_fprintf (stat_out,"  Quadric      %10ld  %10ld  %10.2f", Ray_Quadric_Tests, Ray_Quadric_Tests_Succeeded, ( ((DBL)Ray_Quadric_Tests_Succeeded/(DBL)Ray_Quadric_Tests) *100.0 ));
  2390.    if(Ray_Blob_Tests)
  2391.    box_fprintf (stat_out,"  Blob         %10ld  %10ld  %10.2f", Ray_Blob_Tests, Ray_Blob_Tests_Succeeded, ( ((DBL)Ray_Blob_Tests_Succeeded/(DBL)Ray_Blob_Tests) *100.0 ));
  2392.    if(Ray_Box_Tests)
  2393.    box_fprintf (stat_out,"  Box          %10ld  %10ld  %10.2f", Ray_Box_Tests, Ray_Box_Tests_Succeeded, ( ((DBL)Ray_Box_Tests_Succeeded/(DBL)Ray_Box_Tests) *100.0 ));
  2394.    if(Ray_Poly_Tests)
  2395.    box_fprintf (stat_out,"  Quartic\\Poly %10ld  %10ld  %10.2f", Ray_Poly_Tests, Ray_Poly_Tests_Succeeded, ( ((DBL)Ray_Poly_Tests_Succeeded/(DBL)Ray_Poly_Tests) *100.0 ));
  2396.    if(Ray_Bicubic_Tests)
  2397.    box_fprintf (stat_out,"  Bezier Patch %10ld  %10ld  %10.2f", Ray_Bicubic_Tests, Ray_Bicubic_Tests_Succeeded, ( ((DBL)Ray_Bicubic_Tests_Succeeded/(DBL)Ray_Bicubic_Tests) *100.0 ));
  2398.    if(Ray_Ht_Field_Tests)
  2399.    box_fprintf (stat_out,"  Height Fld   %10ld  %10ld  %10.2f", Ray_Ht_Field_Tests, Ray_Ht_Field_Tests_Succeeded, ( ((DBL)Ray_Ht_Field_Tests_Succeeded/(DBL)Ray_Ht_Field_Tests) *100.0 ));
  2400.    if(Ray_Ht_Field_Box_Tests)
  2401.    box_fprintf (stat_out,"  Hght Fld Box %10ld  %10ld  %10.2f", Ray_Ht_Field_Box_Tests, Ray_HField_Box_Tests_Succeeded, ( ((DBL)Ray_HField_Box_Tests_Succeeded/(DBL)Ray_Ht_Field_Box_Tests) *100.0 ));
  2402.    if(Bounding_Region_Tests)
  2403.    box_fprintf (stat_out,"  Bounds       %10ld  %10ld  %10.2f", Bounding_Region_Tests, Bounding_Region_Tests_Succeeded, ( ((DBL)Bounding_Region_Tests_Succeeded/(DBL)Bounding_Region_Tests) *100.0 ));
  2404.    if(Clipping_Region_Tests)
  2405.    box_fprintf (stat_out,"  Clips        %10ld  %10ld  %10.2f", Clipping_Region_Tests, Clipping_Region_Tests_Succeeded, ( ((DBL)Clipping_Region_Tests_Succeeded/(DBL)Clipping_Region_Tests) *100.0 ));
  2406.    fprintf (stat_out,"║────────────────────────────────────────────────────────────────────────║\n");
  2407.    if(Calls_To_Noise)
  2408.    box_fprintf (stat_out,  "  Calls to Noise Routine  :  %10ld", Calls_To_Noise);
  2409.    if(Calls_To_DNoise)
  2410.    box_fprintf (stat_out,  "  Calls to DNoise Routine :  %10ld", Calls_To_DNoise);
  2411.    fprintf (stat_out,"║────────────────────────────────────────────────────────────────────────║\n");
  2412.    if(Shadow_Ray_Tests){
  2413.      box_fprintf (stat_out,"  Shadow Ray Tests        :  %10ld",Shadow_Ray_Tests);
  2414.      box_fprintf (stat_out,"  Blocking Objects Found  :  %10ld",Shadow_Rays_Succeeded);
  2415.      }
  2416.    if(Reflected_Rays_Traced)
  2417.    box_fprintf (stat_out,  "  Reflected Rays          :  %10ld", Reflected_Rays_Traced);
  2418.    if(Refracted_Rays_Traced)                         
  2419.    box_fprintf (stat_out,  "  Refracted Rays          :  %10ld", Refracted_Rays_Traced);
  2420.    if(Transmitted_Rays_Traced)
  2421.    box_fprintf (stat_out,  "  Transmitted Rays        :  %10ld", Transmitted_Rays_Traced);
  2422.    
  2423.    if(tused==0) {
  2424.     STOP_TIME                  /* Get trace done time. */
  2425.     tused = TIME_ELAPSED       /* Calc. elapsed time. Define TIME_ELAPSED as */
  2426.                   /* 0 in your specific CONFIG.H if unsupported */
  2427.     }
  2428.    if (tused != 0){
  2429.      /* Convert seconds to hours, min & sec. CdW */
  2430.      hours = (int) tused/3600;
  2431.      min = (int) (tused - hours*3600)/60;
  2432.      sec = tused - (DBL) (hours*3600 + min*60);
  2433.      fprintf (stat_out,"║────────────────────────────────────────────────────────────────────────║\n");
  2434.      box_fprintf (stat_out,"  Rendering Time          :   %5d hours %2d minutes %4.2f seconds", hours,min,sec); 
  2435.      }
  2436.      fprintf (stat_out,"╚════════════════════════════════════════════════════════════════════════╝\n");
  2437.  
  2438.     if (Options & VERBOSE_FILE)
  2439.       fclose(stat_out);
  2440.  
  2441. }
  2442.  
  2443.  
  2444. /* Output a string to stream with vfprintf formatted for ibm stat screen. */
  2445. /* String should be <80 chars                 */
  2446. int _cdecl box_fprintf( FILE *stream, char *fmt , ... )
  2447. {                     
  2448.     va_list marker;
  2449.     char buffer[160];
  2450.     int len,i;
  2451.     
  2452.     buffer[0] = '║';
  2453.     va_start( marker, fmt );
  2454.     vsprintf( buffer+1, fmt, marker );
  2455.     va_end( marker );
  2456.     len = strlen (buffer);
  2457.     for(i=len;i<73;i++)
  2458.        buffer[i] = ' ';
  2459.     strcpy (buffer+73,"║\n");   
  2460.     return( fputs(buffer,stream) );
  2461. }
  2462.