home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Raytrace & Morphing / SOS-RAYTRACE.ISO / programm / source / devel5 / rend386.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-08  |  23.7 KB  |  960 lines

  1. /* Written by Bernie Roehl, February 1992 */
  2. /* Latest version (re)written Nov. 7 1992 */
  3. /* by Dave Stampe for book release        */
  4. /* Latest version (re)written Feb. 9 1993 */
  5. /* by Bernie Roehl to add additional features */
  6.  
  7. /* Contact: broehl@sunee.waterloo.edu */
  8. /* Dave Stampe : dstampe@sunee.uwaterloo.edu */
  9. /*
  10.    (c) 1992 by Dave Stampe and Bernie Roehl
  11.    ATTRIBUTION:  If you use any part of this source code or the libraries
  12.    in your projects, you must give attribution to REND386, Dave Stampe,
  13.    and Bernie Roehl in your documentation, source code, and at startup
  14.    of your program.  Let's keep the freeware ball rolling!
  15. */
  16.  
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <math.h>
  20. #include <ctype.h>   /* toupper() */
  21. #include <string.h>
  22. #include <mem.h>     /* memmove() */
  23. #include <dos.h>
  24.  
  25. #include "config.h"
  26. #include "rend386.h"
  27. #include "intmath.h"
  28. #include "plg.h"
  29. #include "segio.h"
  30. #include "segasupp.h"
  31. #include "splits.h"
  32. #include "pointer.h"
  33. #include "tasks.h"
  34. #include "cursor.h"
  35. #include "userint.h"
  36. #include "f3dkitd.h"  /* for load_dac_colors() */
  37.  
  38. extern int animatemode;
  39.  
  40. extern unsigned _stklen = 10000; /* need lots of stack for recursion */
  41. #define XFSC 536870912           /* 2**29 for shifting xform coeffs to <3.29> */
  42.  
  43. FILE *log_file = NULL;
  44.  
  45. /*************** VIEW DATA **************/
  46.  
  47. VIEW default_view = {
  48.     0,0,-8000, /* ex,ey,ez */
  49.     0,0,0, /* pan,tilt,roll */
  50.     4*65536L, /* zoom */
  51.     1000,15000,-5000, /* lx,ly,lz */
  52.     0,63, /* point, ambient */
  53.     0,319,0,200, /* left,right,top,bottom */
  54.     1,100000, /* hither, yon */
  55.     1/1.25*65536L, /* aspect ratio */
  56.     0, /* flags */
  57.     0,0, /* no offset */
  58.     0 /* no flip */
  59. }; /* don't init. matrix */
  60.  
  61. VIEW *current_view = &default_view;
  62.  
  63. VIEW orig_view; /* used for HOME     */
  64. VIEW *current_home_view = &orig_view; /* camera being used */
  65. VIEW real_view; /* camera xform data */
  66.  
  67.  
  68. OBJLIST *objlist; /* the linked list of objects in the scene */
  69.  
  70. int running = 0; /* non-zero while we're in the main loop */
  71. int redraw = 1; /* non-zero if we need a redraw */
  72. int review = 1; /* non-zero if we need to recompute current view */
  73. int reframe = 1; /* non-zero if we need to copy our frame back on-screen */
  74. int v_page = 0; /* screen page swap variable */
  75.  
  76. /************* DRIVER INFORMATION **************/
  77.  
  78. extern struct Screeninfo *screeninfo;
  79.  
  80. char vdname[40] = "vd256.rvd";
  81. int vdmode = 0x14;
  82. int vd_loaded = 0;
  83. extern highest_color;
  84.  
  85. char swdname[40] = "sega";
  86.  
  87. char mdname[40] = "mouse";
  88. PDRIVER *cursor_device = NULL; /* primary mouse device   */
  89. PDRIVER *menu_device = NULL; /* secondary mouse device */
  90. int manip_2D_avail = 0; /* can do mouse manipulation */
  91.  
  92. char gpdname[40] = "pglove";
  93. char gpcursor[40] = "./hand.fig";
  94. float gpdo_x = 1, gpdo_y = 1, gpdo_z = 2, gpdo_rx = 1, gpdo_ry = 1, gpdo_rz = 1;
  95. int have_glove = 0;
  96. int have_ptr = 0;
  97. PDRIVER *manip_device = NULL; /* extended manip. device (glove or pointer) */
  98.  
  99. char hdname[40] = "none";
  100. float hdo_x = 0, hdo_y = 0, hdo_z = 0; /* relative pos'n to neck */
  101. float hdo_rx = 0, hdo_ry = 0, hdo_rz = 0;
  102. PDRIVER *head_device = NULL; /* head tracking device   */
  103. int use_ht = 0;
  104.  
  105.  
  106. MATRIX head_tracker_map = {
  107.     XFSC, 0, 0, 0, XFSC, 0, 0, 0, XFSC, 0, 0, 0 };
  108.  
  109. int have_joystick = 0; /* non-zero if we have one or more joysticks */
  110. joystick_data joy;
  111.  
  112. /************* STEREOSCOPIC DATA ***************/
  113.  
  114.  
  115. STEREO default_stereo = {
  116.     600 , 240, 320, 50, 600, 1*65536L };
  117.  
  118. int stereo_type = MONOSCOPIC;
  119.  
  120. int sl_xflip = 0, sl_xoff = 0;
  121. long sl_left = -1, sl_top, sl_right, sl_bottom;
  122. int sr_xflip = 0, sr_xoff = 0;
  123. long sr_left = -1, sr_top, sr_right, sr_bottom;
  124. float sl_xrot = 0, sr_xrot = 0;
  125.  
  126. /************ OPTIONS FLAGS ***************/
  127.  
  128. int use_BW = 0;
  129. int swap_eyes = 0;
  130. int use_glove = 0;
  131.  
  132. SEGMENT *preconnect_view_seg = NULL; /* if view is to be preconnected */
  133.  
  134. extern int floormode;
  135. int do_horizon = 1;
  136. extern int spinmode;
  137. int fancy_background = 0; /* if set, we display a fancy background */
  138. int reflection_pool = 0; /* if set, draw a "reflecting pool" at the bottom of the screen */
  139. int have_logo = 0; /* if set, we have a logo */
  140. int show_logo = 0; /* if set, show the logo (if we have one) */
  141. int show_location = 1; /* if set, we display the current location on-screen */
  142. int show_compass = 1; /* if set, we display the 3-D compass on-screen */
  143. int show_framerate = 1; /* if set, we display the frames/second rate */
  144. int do_screen_clear = 1; /* by default, we clear the screen on each frame */
  145. int use_frame = 0; /* if set, draw a "frame" */
  146.  
  147.  
  148. /************ MISC. COMMUNICTION *************/
  149.  
  150. int frame_x = 0, frame_y = 0, frame_w = 320, frame_h = 200; /* frame location */
  151.  
  152. extern SEGMENT *light_seg;
  153. extern long light2_x, light2_y ,light2_z;
  154.  
  155. TASK *tasklist = NULL;
  156.  
  157. SPLIT *split_tree = NULL;
  158.  
  159. extern void *temp_mem;
  160. extern long temp_size;
  161.  
  162. long floor_y = 0;
  163. long old_floor_y = 0;
  164.  
  165. int npalette = 0; /* non-zero if we have a palette loaded */
  166. unsigned char palette[256*3];
  167.  
  168. char framefname[100];
  169.  
  170. extern long spacestep;  /* "granularity" of motion */
  171.  
  172. unsigned lastkey = 0, nextolastkey = 0;
  173. char *progname = "REND386";
  174.  
  175.  
  176. /************** LOAD SUPPORT *************/
  177.  
  178. static char tempname[100];
  179. char loadpath[100] = "";
  180.  
  181. char *fix_fname(char *name)
  182. {
  183.     if (loadpath[0] && !strchr(name, '\\') && !strchr(name, '/'))
  184.         sprintf(tempname, "%s\\%s", loadpath, name);
  185.     else
  186.         strcpy(tempname, name);
  187.     return tempname;
  188. }
  189.  
  190. void *v_driver_pointer = NULL;
  191.  
  192. void load_video_driver(char *dfile)
  193. {
  194.     v_driver_pointer = load_driver(dfile);
  195.     if (v_driver_pointer == NULL)
  196.     {
  197.         fprintf(stderr,"Cannot read video driver %s\n", dfile);
  198.         exit(0);
  199.     }
  200. }
  201.  
  202. /************** MAIN PROGRAM ***************/
  203.  
  204. void main(int argc, char *argv[])
  205. {
  206.     OBJECT *obj;
  207.     void wrap(void); /* wrap-up function, shuts everything down */
  208.     void joystick_calibration(joystick_data *joy), refresh_display(void);
  209.     long x, y, z;
  210.     FILE *in;
  211.     int i;
  212.     PDRIVER *dm;
  213.     POINTER *p;
  214.     char *fname; /* environment setup */
  215.  
  216.     if ((progname = strrchr(argv[0], '.')) != NULL) *progname = '\0';
  217.     progname = argv[0];
  218.  
  219.     if (getenv("REND386"))
  220.         strcpy(loadpath, getenv("REND386"));
  221.  
  222.     title_screen();
  223.     /* renderer setup */
  224.  
  225.     temp_mem = setup_render(55,1000); /* # of K, # of polys */
  226.     temp_size = 55000L;
  227.     atexit(wrap);
  228. #ifdef ENABLE_STATEMACH
  229.     create_default_segs(); /* for animations */
  230. #endif
  231.     set_global_split_root(&split_tree);
  232.     initial_world_split(&split_tree);
  233.     set_move_handler(split_move_handler);
  234.     objlist = new_objlist();
  235.     /* configuration file loading */
  236.     i = 1;
  237.     if ((!stricmp(&(argv[1][0]), "/C"))||(!stricmp(&(argv[1][0]), "-C")))
  238.     {
  239.         i = 2;
  240.         fname = &(argv[2][0]);
  241.     }
  242.     else fname = "rend386.cfg";
  243.  
  244.     if ((in = fopen(fname, "r")) == NULL)
  245.         fprintf(stderr, "Note -- config file '%s' not found; using defaults.\n", fname);
  246.     else
  247.         {
  248.         if (read_world(in))
  249.             fprintf(stderr, "Error reading config file '%s'\n", fname);
  250.         fclose(in);
  251.     }
  252.             /* preload video driver to set defaults */
  253.     load_video_driver(vdname);
  254.     screeninfo = screen_data();
  255.     highest_color = screeninfo->colors-1;
  256.     preset_default_colors();
  257.  
  258.     frame_x = screeninfo->xmin;
  259.     frame_y = screeninfo->ymin;
  260.     frame_w = screeninfo->xmax - screeninfo->xmin + 1;
  261.     frame_h = screeninfo->ymax - screeninfo->ymin + 1;
  262.  
  263.             /* Default view is full-screen: */
  264.     default_view.left = screeninfo->xmin;
  265.     default_view.top = screeninfo->ymin;
  266.     default_view.right = screeninfo->xmax;
  267.     default_view.bottom = screeninfo->ymax;
  268.     default_view.aspect = screeninfo->aspect;
  269.  
  270.     for (; i < argc; ++i)
  271.     {
  272.         if (argv[i][0] == '/' || argv[i][0] == '-')
  273.         {
  274.             switch(toupper(argv[i][1]))
  275.             {
  276.             case 'L':/* log file */
  277.                 {
  278.                  char *lf;
  279.                  if (argv[i][2]) lf = &argv[i][2];
  280.                  else lf = argv[++i];
  281.                  log_file = fopen(lf, "w");
  282.                  if (log_file == NULL)
  283.                   {
  284.                    fprintf(stderr, "Could not open log file '%s'\n", lf);
  285.                    exit(2);
  286.                   }
  287.                 }
  288.                 break;
  289.             case 'M':/* disable MS mouse */
  290.                 mdname[0] = 0;
  291.                 break;
  292.             case 'R':/* swap eyes on Sega driver */
  293.                 swap_eyes = 1;
  294.                 break;
  295.             case 'D':/* set conv. distance */
  296.                 default_stereo.phys_screen_dist = atol(argv[++i]);
  297.                 break;
  298.             case 'S':/* set world scale */
  299.                 default_stereo.world_scaling = 65536.0*atof(argv[++i]);
  300.                 break;
  301.             case 'E':/* set eye spacing */
  302.                 default_stereo.phys_eye_spacing = atol(argv[++i]);
  303.                 break;
  304.             case 'X':/* turn on stereo */
  305.                 stereo_type = SWITCHED;
  306.                 break;
  307.             case 'J':/* sort by object (default is polys) */
  308.                 set_default_depth_sort(get_default_depth_sort() | BYOBJECT);
  309.                 break;
  310.             case 'P':/* depth sort-- deepest */
  311.                 set_default_depth_sort(get_default_depth_sort() & (~(BYOBJECT|AVERAGE|ATBACK)));
  312.                 break;
  313.             case 'A':/* depth sort-- middle */
  314.                 set_default_depth_sort(get_default_depth_sort() | AVERAGE);
  315.                 break;
  316.             case '1':/* com 1 for SEGA */
  317.                 select_sega_port(0x3FC);
  318.                 break;
  319.             case '2':/* com 2 for SEGA */
  320.                 select_sega_port(0x2FC);
  321.                 break;
  322.             case 'G':/* enable glove */
  323.                 use_glove = 1;
  324.                 if (!have_ptr) have_glove = 1;
  325.                 break;
  326.             case 'H':/* enable head tracker */
  327.                 use_ht = 1;
  328.                 break;
  329.             case 'B':/* force all colors to monochrome */
  330.                 use_BW = 1;
  331.                 break;
  332.             }
  333.         }
  334.         else
  335.             {
  336.             char *in_filename;
  337.             in_filename = fix_fname(argv[i]);
  338.             if ((in = fopen(in_filename, "r")) == NULL)
  339.                 fprintf(stderr, "Could not open '%s'\n", in_filename);
  340.             else if (strstr(in_filename,".plg")) /* check if plg or fig file */
  341.             {
  342.                 set_loadplg_offset(0,0,0);
  343.                 set_loadplg_scale(1,1,1);
  344.                 while ((obj = load_plg(in)) != NULL)
  345.                 {
  346.                     SEGMENT *s;
  347.                     add_to_objlist(objlist, obj);
  348.                     if ((s = new_seg(NULL)) == NULL)
  349.                         fprintf(stderr, "Warning: out of memory while loading an object\n");
  350.                     else
  351.                         {
  352.                         seg_set_object(s, obj);
  353.                         set_object_owner(obj, s);
  354.                         update_segment(s);
  355.                     }
  356. /*            if (spacestep < get_object_bounds(obj, &x, &y, &z)/5L)
  357.                         spacestep = get_object_bounds(obj, &x, &y, &z)/5L; */
  358.                 }
  359.                 if (load_err)
  360.                 {
  361.                     fprintf(stderr, "Load error: %s in file '%s'\n", plg_errmsgs[-load_err], in_filename);
  362.                     if (log_file)
  363.                         fprintf(log_file, "%s on line %d of file %s\n", plg_errmsgs[-load_err], err_line, in_filename);
  364.                     getkey();
  365.                 }
  366.             }
  367.             else if (strstr(in_filename,".fig")) /* check if plg or fig file */
  368.             {
  369.                 SEGMENT *s;
  370.                 int c;
  371.                 set_readseg_objlist(objlist);
  372.                 readseg_err = 0;
  373.                 if ((s = readseg(in, NULL)) == NULL)
  374.                     if (readseg_err && log_file) {
  375.                         fprintf(log_file, "%s while reading figure file '%s'\n", readseg_errmsgs[-readseg_err], argv[i]);
  376.                         fprintf(stderr, "%s while reading figure file '%s'\n", readseg_errmsgs[-readseg_err], argv[i]);
  377.                     }
  378.                 else
  379.                     update_segment(s);
  380.             }
  381.             else
  382.                 {
  383.                 if (read_world(in)) {
  384.                     fprintf(stderr, "Error reading world file\n");
  385.                     if (log_file)
  386.                         fprintf(log_file, "Error while reading world file\n");
  387.                 }
  388.             }
  389.             fclose(in);
  390.         }
  391.     }
  392.  
  393.     dump_lists(); /* get rid of temps used by world loader */
  394.  
  395.     /* end of world loading: now process the driver stuff */
  396.  
  397.     have_joystick = joystick_check();
  398.  
  399.     wait_for_title();
  400.  
  401.     if (enter_graphics())
  402.     {
  403.         fprintf(stderr, "Could not enter graphics mode\n");
  404.         exit(1);
  405.     }
  406.     vd_loaded++;
  407.  
  408.     frame_x = screeninfo->xmin; /* reload in case driver changed it */
  409.     frame_y = screeninfo->ymin;
  410.     frame_w = screeninfo->xmax - screeninfo->xmin + 1;
  411.     frame_h = screeninfo->ymax - screeninfo->ymin + 1;
  412.  
  413.     /* Default view is full-screen: */
  414.     default_view.left = screeninfo->xmin;
  415.     default_view.top = screeninfo->ymin;
  416.     default_view.right = screeninfo->xmax;
  417.     default_view.bottom = screeninfo->ymax;
  418.     default_view.aspect = screeninfo->aspect;
  419.  
  420.  
  421.     initialize_screen_factors(current_view);
  422.     fast_view_factors(current_view);
  423.  
  424.     if (npalette)
  425.         load_DAC_colors(palette, highest_color+1, use_BW);
  426.  
  427.     if (use_frame)
  428.     {
  429.         FILE *in;
  430.         char *f;
  431.         use_frame = 0; /* we only set it back to 1 if we're successful */
  432.         if (stereo_type == MONOSCOPIC)
  433.             if ((in = fopen(f = fix_fname(framefname), "rb")) != NULL)
  434.             {
  435.                 if (load_pcx(in, 3) == 0) use_frame = 1;
  436.                 copy_block(3, 0, 0, 0, frame_x, frame_y, frame_w, frame_h);
  437.                 copy_block(3, 0, 0, 1, frame_x, frame_y, frame_w, frame_h);
  438.                 copy_block(3, 0, 0, 2, frame_x, frame_y, frame_w, frame_h);
  439.                 fclose(in);
  440.             }
  441.         else {
  442.             char tbuff[100];
  443.             sprintf(tbuff, "Could not open '%s'", f);
  444.             if (running)
  445.                 popmsg(tbuff);
  446.             else
  447.                 fprintf(stderr, "%s\n", tbuff);
  448.             if (log_file)
  449.                 fprintf(log_file, "%s\n", tbuff);
  450.         }
  451.     }
  452.  
  453.     init_body_links();
  454.  
  455.     if (stereo_type != MONOSCOPIC)
  456.     {
  457.         init_switch_driver(swdname);
  458.  
  459.         if (sl_left<0)
  460.         {
  461.             sl_left = default_view.left;
  462.             sl_right = default_view.right;
  463.             sl_top = default_view.top;
  464.             sl_bottom = default_view.bottom;
  465.         }
  466.         compute_stereo_data(&default_stereo, 0, sl_xflip, sl_xoff, 65536.0*sl_xrot,
  467.         sl_left, sl_top, sl_right, sl_bottom);
  468.  
  469.         if (sr_left<0)
  470.         {
  471.             sr_left = default_view.left;
  472.             sr_right = default_view.right;
  473.             sr_top = default_view.top;
  474.             sr_bottom = default_view.bottom;
  475.         }
  476.         compute_stereo_data(&default_stereo, 1, sr_xflip, sr_xoff, 65536.0*sr_xrot,
  477.         sr_left, sr_top, sr_right, sr_bottom);
  478.     }
  479.  
  480.     orig_view = default_view;
  481.     real_view = default_view;
  482.  
  483.     if (stricmp(hdname,"none") && use_ht)
  484.     {
  485.         extern PDRIVER *init_head_device(char *name, long x, long y, long z, long rx, long ry, long rz);
  486.         head_device = init_head_device(hdname, hdo_x, hdo_y, hdo_z,
  487.             hdo_rx*65536.0, hdo_ry*65536.0, hdo_rz*65536.0);
  488.     }
  489.  
  490.     if ((dm=mouseptr_init(mdname))!=NULL)
  491.     {
  492.         cursor_show(v_page);
  493.         manip_2D_avail++;
  494.     }
  495.     cursor_device = dm;
  496.     menu_device = dm;
  497.  
  498.     if ((!use_glove) || have_ptr || stricmp(gpdname,"pglove"))
  499.         /* not going to be using powerglove */
  500.     {
  501.         if (stereo_type==SWITCHED)
  502.             init_SG_interrupt(switch_sega,NULL,6500);
  503.         else init_timer();
  504.     }
  505.  
  506.     if (use_glove && (!have_ptr))
  507.     {
  508.         extern SEGMENT *body_seg;
  509.         PDRIVER *gd;
  510.         extern PDRIVER *gloveptr_init(char *gname, long sx, long sy, long sz, long srx, long sry, long srz);
  511.  
  512.         gd = gloveptr_init(gpdname, gpdo_x*65536.0, gpdo_y*65536.0, gpdo_z*65536.0,
  513.         gpdo_rx*65536.0, gpdo_ry*65536.0, gpdo_rz*65536.0);
  514.         manip_device = menu_device = gd;
  515.         if (gd) {
  516.             set_readseg_scale(1.0,1.0,1.0);
  517.             switch (load_glove_cursor(body_seg, manip_device, fix_fname(gpcursor))) {
  518.             case 0:
  519.                 break; /* all is well */
  520.             case -1:
  521.                 popmsg("Could not open glove cursor file");
  522.                 getkey();
  523.                 if (log_file)
  524.                     fprintf(log_file, "Could not open glove cursor file '%s'\n", fix_fname(gpcursor));
  525.                 have_glove = use_glove = 0;
  526.                 break;
  527.             case -2:
  528.                 popmsg("Error while loading glove cursor");
  529.                 getkey();
  530.                 if (log_file)
  531.                     fprintf(log_file, "Error while loading glove cursor file '%s'\n", fix_fname(gpcursor));
  532.                 have_glove = use_glove = 0;
  533.                 break;
  534.             default:
  535.                 popmsg("Unknown error loading glove cursor");
  536.                 getkey();
  537.                 if (log_file)
  538.                     fprintf(log_file, "Unknown error while loading glove cursor file '%s'\n", fix_fname(gpcursor));
  539.                 have_glove = use_glove = 0;
  540.                 break;
  541.             }
  542.         }
  543.         else have_glove = use_glove = 0;
  544.     }
  545.  
  546.     if (use_glove && have_ptr)
  547.     {
  548.         extern SEGMENT *body_seg;
  549.         PDRIVER *gd;
  550.         extern PDRIVER *gloveptr_init(char *gname, long sx, long sy, long sz, long srx, long sry, long srz);
  551.  
  552.         gd = gloveptr_init(gpdname, gpdo_x*65536.0, gpdo_y*65536.0, gpdo_z*65536.0,
  553.         gpdo_rx*65536.0, gpdo_ry*65536.0, gpdo_rz*65536.0);
  554.         manip_device = menu_device = gd;
  555.         if (gd)
  556.         {
  557.             set_loadplg_offset(0, 0, 0);
  558.             set_loadplg_scale(1, 1, 1);
  559.             switch (load_3D_cursor(body_seg, manip_device, fix_fname(gpcursor))) {
  560.             case 0:
  561.                 break; /* all is well */
  562.             case -1:
  563.                 popmsg("Could not open 3D cursor file");
  564.                 getkey();
  565.                 if (log_file)
  566.                     fprintf(log_file, "Could not open 3D cursor file '%s'\n", fix_fname(gpcursor));
  567.                 have_glove = use_glove = 0;
  568.                 break;
  569.             case -2:
  570.                 popmsg("Error while loading 3D cursor");
  571.                 getkey();
  572.                 if (log_file)
  573.                     fprintf(log_file, "Error while loading 3D cursor file '%s'\n", fix_fname(gpcursor));
  574.                 have_glove = use_glove = 0;
  575.                 break;
  576.             default:
  577.                 popmsg("Unknown error loading 3D cursor");
  578.                 getkey();
  579.                 if (log_file)
  580.                     fprintf(log_file, "Unknown error while loading 3D cursor file '%s'\n", fix_fname(gpcursor));
  581.                 have_glove = use_glove = 0;
  582.                 break;
  583.             }
  584.         }
  585.         else have_ptr = use_glove = 0;
  586.     }
  587.  
  588.     if ((have_joystick) != 0)
  589.     {
  590.         joystick_calibration(&joy);
  591.     }
  592.  
  593.     {
  594.         extern char *title[];
  595.         long j;
  596.  
  597.         if (title[0])
  598.         {
  599.             refresh_display();
  600.             poptext(title);
  601.             j = current_time();
  602.             while ((current_time()-j) < 330)
  603.             {
  604.              if (goodbye()) break;
  605.             }
  606.             while (kbhit()) getch();
  607.             refresh_display();
  608.         }
  609.     }
  610.  
  611.     if (preconnect_view_seg)
  612.         connect_body(current_view, preconnect_view_seg);
  613.  
  614.     running = 1;
  615.     while (running)
  616.     {
  617.         int x, y;
  618.         unsigned buttons;
  619.  
  620.         old_floor_y = floor_y;
  621.         {
  622.             AREA *a;
  623.             long x,y,z;
  624.             real_viewpoint(&real_view, &x, &y, &z);
  625.             a = what_area(split_tree, x, y, z);
  626.             if (a)
  627.             {
  628.                 floor_y = floor_at(a, x, z);
  629.                 if (floor_y == 0x7FFFFFFFL) floor_y = old_floor_y;
  630.             }
  631.             else floor_y = old_floor_y;
  632.         }
  633.  
  634.         if (mouse_joy(&joy)) do_joy(&joy);
  635.         else
  636.             {
  637.             if (cursor_device)
  638.                 if (move_and_select_2D(cursor_device) == -1) do_key('X');
  639.             if (have_joystick && joystick_read(&joy)) do_joy(&joy);
  640.         }
  641.  
  642.         if (animatemode==-1) animatemode = 0; /* single step OFF */
  643.  
  644.         if (bioskey(1))
  645.         {
  646.             nextolastkey = getkey();
  647.             while(bioskey(1)) getkey();
  648.             do_key(nextolastkey);
  649.             lastkey = nextolastkey;
  650.         }
  651.  
  652.         if (floormode) current_view->ey += floor_y - old_floor_y;
  653.  
  654.         if (head_device && use_ht) head_update(0);
  655.  
  656.         if (use_glove)
  657.         {
  658.             POINTER gp;
  659.             int g;
  660.  
  661.             if (!have_ptr)
  662.             {
  663.                 glove_update(manip_device, &gp);
  664.                 switch(gp.gesture)
  665.                 {
  666.                 case G_FIST :
  667.                     g = GRASP_DO;
  668.                     break;
  669.                 case G_PINCH:
  670.                     g = ROTATE_DO;
  671.                     break;
  672.                 case G_POINT:
  673.                     g = SELECT_DO;
  674.                     break;
  675.                 default:
  676.                     g = FREE_DO;
  677.                     break;
  678.                 }
  679.             }
  680.             else
  681.                 {
  682.                 cursor_update3D(manip_device, &gp);
  683.                 switch(gp.buttons)
  684.                 {
  685.                 case 2:
  686.                     g = GRASP_DO;
  687.                     break;
  688.                 case 3:
  689.                     g = ROTATE_DO;
  690.                     break;
  691.                 case 1:
  692.                     g = SELECT_DO;
  693.                     break;
  694.                 default:
  695.                     g = FREE_DO;
  696.                     break;
  697.                 }
  698.             }
  699.  
  700.             manip_do(manip_device,g);
  701.         }
  702.  
  703.         if (animatemode)
  704.         {
  705.             run_tasks(tasklist);
  706. #ifdef ENABLE_STATEMACH
  707.             do_animations();
  708. #endif
  709.             if (light_seg) seg_getposxyz(light_seg, &light2_x, &light2_y, &light2_z);
  710.         }
  711.  
  712.         if (redraw) refresh_display();
  713.     }
  714. }
  715.  
  716.  
  717. static char *closing_msg[] = {
  718.     "",
  719.     "Thank you for trying REND386, the first freeware VR",
  720.     "system for PC users.  It was written by Dave Stampe and",
  721.     "Bernie Roehl, and continues to evolve.  This version, ",
  722.     "Release 5, was written for distribution with Virtual",
  723.     "Reality Creations, published by The Waite Group.",
  724.     NULL };
  725.  
  726.  
  727. void wrap(void) /* end program */
  728. {
  729.     int i;
  730.  
  731.     if (have_joystick) joystick_quit();
  732.     if (vd_loaded) exit_graphics();
  733.     reset_render();
  734. /*
  735.     for (i = 0; closing_msg[i]; ++i)
  736.         fprintf(stderr, "%s\n", closing_msg[i]);
  737. */
  738.     if (log_file) fclose(log_file);
  739.     exit(0);
  740. }
  741.  
  742.  
  743. void refresh_display()
  744. {
  745.     if (spinmode) polar_compute();
  746.  
  747.     initialize_screen_factors(current_view);
  748.  
  749.     body_centric_map(current_view, &real_view);
  750.     screen_refresh(&real_view);
  751.  
  752.     redraw = 0;
  753. }
  754.  
  755.  
  756. load_logo(char *filename)
  757. {
  758.     char far *buffer;
  759.     FILE *in;
  760.     char *f;
  761.     if ((in = fopen(f = fix_fname(filename), "rb")) == NULL) {
  762.         char tbuff[100];
  763.         sprintf(tbuff, "Could not open '%s'", f);
  764.         if (running)
  765.             popmsg(tbuff);
  766.         else
  767.             fprintf(stderr, "%s\n", tbuff);
  768.         if (log_file)
  769.             fprintf(log_file, "%s\n", tbuff);
  770.         return 0;
  771.     }
  772.     if (load_pcx(in, 3)) { /* some sort of problem loading it in */
  773.         fclose(in);
  774.         return 0;
  775.     }
  776.     fclose(in);
  777.     return 1; /* all is well... we have a logo */
  778. }
  779.  
  780. int resize_viewport(void)
  781. {
  782.     int top, left, bottom, right;
  783.     unsigned buttons;
  784.     cursor_hide();
  785.     clear_display(v_page);
  786.     cursor_show(v_page);
  787.     popmsg("Click top-left and drag");
  788.  
  789.     do {
  790.         move_2D(cursor_device, &left, &top, &buttons);
  791.         if(kbhit())
  792.          {
  793.           getch();
  794.           refresh_display();
  795.           return 1;
  796.          }
  797.     }
  798.     while (buttons == 0);
  799.     while (buttons) {
  800.         while (!move_2D(cursor_device, &right, &bottom, &buttons));
  801.         clear_display(v_page);
  802.         vgabox(left, top, right, bottom, 15);
  803.     }
  804.     if (right - left > 10) {
  805.         current_view->left = left & (~0x0007); /* always on a 16-pixel boundary */
  806.         current_view->right = (right & (~0x0007)) + 7;
  807.     }
  808.     if (bottom - top > 10) {
  809.         current_view->top = top;
  810.         current_view->bottom = bottom;
  811.     }
  812.  
  813.     if (stereo_type == SWITCHED) /* makes sense for Sega only (no shift) */
  814.     {
  815.         compute_stereo_data(&default_stereo, 0, sl_xflip, sl_xoff, 65536.0*sl_xrot,
  816.         current_view->left, current_view->top, current_view->right, current_view->bottom);
  817.         compute_stereo_data(&default_stereo, 1, sr_xflip, sr_xoff, 65536.0*sr_xrot,
  818.         current_view->left, current_view->top, current_view->right, current_view->bottom);
  819.     }
  820.  
  821.     /* Make sure all pages are refreshed: */
  822.     reset_screens();
  823.     refresh_display();
  824.     return 0;
  825. }
  826.  
  827. int save_pcx_file(void)
  828. {
  829.     char filename[100];
  830.     char far *buffer;
  831.     FILE *out;
  832.     refresh_display();
  833.     askfor("File to save to? ", filename, 15);
  834.     reframe = 1;
  835.     if (filename[0] == '\0') return 1;
  836.     refresh_display();
  837.     if ((out = fopen(filename, "wb")) == NULL) {
  838.         popmsg("Could not open file");
  839.         reframe = 1;
  840.         getkey();
  841.         return 3;
  842.     }
  843.     cursor_hide();
  844.     save_pcx(out, v_page);
  845.     cursor_show(v_page);
  846.     fclose(out);
  847.     return 0;
  848. }
  849.  
  850.  
  851. int screendump(void) /* alt-F10 */
  852. {
  853.     char filename[30] = "scrn0000.pcx";
  854.     char far *buffer;
  855.     FILE *out;
  856.     int i;
  857.  
  858.     for (i = 0; i < 30; i++) /* find a screendump number */
  859.     {
  860.         sprintf(filename,"scrn%c%d.pcx",
  861.         stereo_type==SWITCHED ? 'L' : '_' , i+1);
  862.         if ((out=fopen(filename,"rb"))==NULL) goto doit;
  863.         fclose(out);
  864.     }
  865.     return 3;
  866.  
  867. doit:
  868.     if(stereo_type!=SWITCHED)
  869.      {
  870.       if ((out = fopen(filename, "wb")) == NULL) return 3;
  871.       save_pcx(out, v_page);
  872.       fclose(out);
  873.       return 0;
  874.      }
  875.     else
  876.      {
  877.       filename[4] = 'L';
  878.       if ((out = fopen(filename, "wb")) == NULL) return 3;
  879.       save_pcx(out, left_page);
  880.       fclose(out);
  881.       filename[4] = 'R';
  882.       if ((out = fopen(filename, "wb")) == NULL) return 3;
  883.       save_pcx(out, right_page);
  884.       fclose(out);
  885.       return 0;
  886.      }
  887. }
  888.  
  889. /* Some support routines */
  890.  
  891.  
  892. void joystick_calibration(joystick_data *joy)
  893. {
  894.     if (have_joystick == 0) return;
  895.     if (have_joystick & 1) joystick_init(joy, 0);
  896.     else if (have_joystick & 2) joystick_init(joy, 1);
  897.  
  898.     joystick_setscale(joy, 100);
  899.     reframe = 1;
  900. }
  901.  
  902. extern AREA *areas;
  903.  
  904. extern POINTER gloveptr;
  905.  
  906. char *gest[] = {
  907.     "FLAT", "THUMB_IN", "INDEX_IN", "MIDDLE_IN",
  908.     "RING_IN", "PINCH", "FIST", "THUMB_OUT", "POINT",
  909.     "BADFINGER", "RING_OUT", "??????" };
  910.  
  911. void prprint(int x,int y, int color, char *t)
  912. {
  913.     int bk = (color>8) ? 0 : 15;
  914.  
  915.     printxyr(x,y,bk,t,0);
  916.     printxyr(x+1,y+1,color,t,0);
  917. }
  918.  
  919. int status_on_screen(void)
  920. {
  921.     char buff[100];
  922.     AREA *a, *what_area();
  923.     long floor_at(), ceiling_at();
  924.     long x, y, z;
  925.  
  926.     if (show_location == 0) return 0;
  927.     real_viewpoint(&real_view, &x, &y, &z);
  928.  
  929.     sprintf(buff, "Pos(x,z): %ld,%ld", x, z);
  930.     prprint(2,3,15,buff);
  931.     sprintf(buff, "Not in any area");
  932.     a = what_area(split_tree, x, y, z);
  933.     if (a)
  934.     {
  935.         char *p = area_name(a);
  936.         if (p)
  937.         {
  938.             sprintf(buff, "Area: %s", p);
  939.             prprint(2,15,15,buff);
  940.         }
  941.     }
  942.  
  943.     if (use_glove && manip_device) /* prevent pre-init call */
  944.     {
  945.         int sl;
  946.         POINTER p;
  947.         extern PDRIVER *manip_device;
  948.  
  949.         last_pointer(manip_device, &p);
  950.         sl = p.gesture;
  951.         if (sl<0 || sl>G_UNKNOWN) sl = G_UNKNOWN;
  952.         sprintf(buff,"Glove: %s",gest[sl]);
  953.         sl = strlen(buff)<<3;
  954.         prprint(300-sl,3,15,buff);
  955.     }
  956.     return 0;
  957.  
  958. }
  959.  
  960.