home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Raytrace & Morphing / SOS-RAYTRACE.ISO / programm / source / devel5 / wparse.c < prev   
Encoding:
C/C++ Source or Header  |  1993-05-09  |  49.6 KB  |  2,136 lines

  1. /* Read a World Description File */
  2.  
  3. /* Written by Bernie Roehl, July 1992 */
  4. /* Rewritten for animation and configuration by Dave Stampe Oct. '92 */
  5.  
  6. /* Copyright 1992 by Dave Stampe and Bernie Roehl.
  7.    May be freely used to write software for release into the public domain;
  8.    all commercial endeavours MUST contact Bernie Roehl and Dave Stampe
  9.    for permission to incorporate any part of this software into their
  10.    products!
  11.  
  12.      ATTRIBUTION:  If you use any part of this source code or the libraries
  13.      in your projects, you must give attribution to REND386, Dave Stampe,
  14.      and Bernie Roehl in your documentation, source code, and at startup
  15.      of your program.  Let's keep the freeware ball rolling!
  16.  */
  17.  
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include <stdlib.h>
  21. #include <alloc.h>
  22. #include <dos.h>       /* delay() */
  23.  
  24. #include "config.h"
  25. #include "rend386.h"
  26. #include "tasks.h"
  27. #include "plg.h"
  28. #include "intmath.h"
  29. #include "splits.h"
  30. #include "pointer.h"
  31. #include "cursor.h"
  32. #include "segasupp.h"
  33. #include "segio.h"
  34. #ifdef ENCRYPT
  35. #include "encrypt.h"
  36. #endif
  37.  
  38. extern FILE *log_file;
  39.  
  40. extern SPLIT *split_tree;
  41.  
  42. extern int sl_xflip, sl_xoff;
  43. extern long sl_left, sl_top, sl_right, sl_bottom;
  44. extern int sr_xflip, sr_xoff;
  45. extern long sr_left, sr_top, sr_right, sr_bottom;
  46. extern float sl_xrot, sr_xrot;
  47.  
  48. extern int running;
  49.  
  50. int old_angle_order = 0;  /* if non-zero, camera angles are pan,tilt,roll */
  51.  
  52. extern unsigned screen_clear_color,sky_color,ground_color;
  53. extern int use_frame, redraw, review, reframe, do_screen_clear;
  54. extern int frame_x, frame_y, frame_w, frame_h;
  55. extern int flymode, floormode;
  56. extern char framefname[];
  57. extern STEREO default_stereo;
  58. extern VIEW default_view;
  59. extern unsigned char palette[];
  60. extern int npalette;
  61. extern OBJLIST *objlist;
  62. extern TASK *tasklist;
  63. extern VIEW *current_view;
  64. extern SEGMENT *preconnect_view_seg;
  65.  
  66. extern char *fix_fname(char *fname);
  67.  
  68. long frame_number = 1; /* current frame number */
  69.  
  70. static int save_frames = 0; /* if non-zero, save a pcx file on "frame" */
  71. static int key_wait = 0; /* if non-zero, wait for a keypress per frame */
  72. static int frame_delay = 0; /* how long to delay on encountering "frame" */
  73. static char pcx_pattern[100] = "f%d.pcx";
  74.  
  75. void *temp_mem = NULL; /* points to area to be used for temp storage */
  76. long temp_size = 0;
  77.  
  78. static int keep_around = 1; /* if non-zero, don't use temp for names */
  79.  
  80. OBJECT *where_split_screen_pt(int *pol, int *vert, int x, int y)
  81. {
  82.     extern OBJECT *render_check_monitor(int *pol, int *vert);
  83.  
  84.     render_monitor_point(x, y);
  85.     refresh_display();
  86.     return render_check_monitor(pol, vert);
  87. }
  88.  
  89. /**************** NAMED LIST SUPPORT **************/
  90.  
  91. typedef struct _name NAMEREF;
  92.  
  93. struct _name {
  94.     char *name;
  95.     void *value;
  96.     NAMEREF *next;
  97. };
  98.  
  99. NAMEREF *add_name(NAMEREF **list, char *name, void *value)
  100. {
  101.     NAMEREF *p;
  102.     /* check if temp usable */
  103.     if (!keep_around && (temp_mem) &&
  104.         (temp_size>(sizeof(NAMEREF)+strlen(name)+1)))
  105.     {
  106.         p = temp_mem;
  107.         temp_mem = ((char *)temp_mem) + sizeof(NAMEREF);
  108.         p->name = temp_mem;
  109.         temp_mem = ((char *)temp_mem) + strlen(name) + 1;
  110.         strcpy(p->name, name);
  111.         temp_size -= sizeof(NAMEREF)+strlen(name)+1;
  112.     }
  113.     else /* use heap */
  114.     {
  115.         temp_mem = NULL;
  116.         if ((p = malloc(sizeof(NAMEREF))) == NULL) return NULL;
  117.         p->name = strdup(name);
  118.     }
  119.     p->value = value;
  120.     p->next = *list;
  121.     *list = p;
  122.     return *list;
  123. }
  124.  
  125. void del_namelist(NAMEREF *list)
  126. {
  127.     if (keep_around) return;
  128.     if (temp_mem) return;
  129.     while (list)
  130.     {
  131.         if (list->name) free(list->name);
  132.         free(list);
  133.         list = list->next;
  134.     }
  135. }
  136.  
  137. void *find_name(NAMEREF *list, char *name)
  138. {
  139.     while (list) {
  140.         if (!stricmp(list->name, name))
  141.             return list->value;
  142.         list = list->next;
  143.     }
  144.     return NULL;
  145. }
  146.  
  147. char *find_value(NAMEREF *list, void *value)
  148. {
  149.     while (list) {
  150.         if (list->value == value)
  151.             return list->name;
  152.         list = list->next;
  153.     }
  154.     return NULL;
  155. }
  156.  
  157. unsigned int find_color(NAMEREF *list, char *name)
  158. {
  159.  
  160.     if (isdigit(name[0])) /* handle dec/hex color */
  161.         return strtoul(name, NULL, 0);
  162.     if (name[0] == '&') return convert_color(&name[1], NULL);
  163.     return (unsigned)find_name(list, name);
  164. }
  165.  
  166.  
  167.  
  168. /****************** TASK AND CONTROL SUPPORT *************/
  169.  
  170. typedef struct _key KEY;
  171.  
  172. struct _key {
  173.     unsigned key;
  174.     void (*fn)();
  175.     unsigned param;
  176.     KEY *next;
  177. };
  178.  
  179. KEY *keylist = NULL;
  180.  
  181. typedef struct _control CONTROL;
  182.  
  183. struct _control {
  184.     int x, y, w, h;
  185.     unsigned buttonmask;
  186.     void (*fn)();
  187.     unsigned param;
  188.     CONTROL *next;
  189. };
  190.  
  191. CONTROL *controllist = NULL;
  192.  
  193. #define MAXSPINCOLORS 100
  194.  
  195. typedef struct {
  196.     OBJECT *obj;
  197.     int np; /* number of polys in obj */
  198.     int ncolors;
  199.     unsigned colors[MAXSPINCOLORS];
  200. }
  201. SPINDATA;
  202.  
  203.  
  204. extern PDRIVER *menu_device;
  205.  
  206. void clickfn(int cmd, unsigned *msg)
  207. {
  208.     char buff[100];
  209.     int x, y;
  210.     unsigned buttons;
  211.     if (cmd == 3) {
  212.         sprintf(buff, "button %u", *msg);
  213.         popmsg(buff);
  214.         /*        do {
  215.                             mouse_read(&x, &y, &buttons);   NEEDS PTR DEVICE UPDATE
  216.                         }
  217.                         while (buttons & 1);
  218.                 */     }
  219.     else if (cmd == 2) {
  220.         sprintf(buff, "key %u", *msg);
  221.         popmsg(buff);
  222.         getkey();
  223.     }
  224.     reframe = redraw = 1;
  225. }
  226.  
  227. check_key(unsigned key)
  228. {
  229.     KEY *p;
  230.     for (p = keylist; p; p = p->next)
  231.         if (key == p->key)
  232.         {
  233.             p->fn(2, &p->param);
  234.             return 1;
  235.         }
  236.     return 0;
  237. }
  238.  
  239. check_controls(int x, int y, unsigned buttons)
  240. {
  241.     CONTROL *p;
  242.     for (p = controllist; p; p = p->next)
  243.         if (x >= p->x && y >= p->y && x < (p->x + p->w) && y < (p->y + p->h) && (buttons & p->buttonmask)) {
  244.             p->fn(3, &p->param);
  245.             return 1;
  246.         }
  247.     return 0;
  248. }
  249.  
  250.  
  251. extern void spinner(), sculspin();
  252.  
  253. struct {
  254.     char *name;
  255.     void (*fn)();
  256. }
  257. functions[] = {
  258.     { 
  259.         "spinner", spinner     }
  260.     ,
  261.     { 
  262.         "sculspin", sculspin     }
  263.     ,
  264.     { 
  265.         "clickfn", clickfn     }
  266.     ,
  267.     { 
  268.         NULL, NULL     }
  269. };
  270.  
  271.  
  272.  
  273. /******************** POLYGON, PLANE NORMAL SUPPORT ***********/
  274.  
  275. #define LSCALE 536870912.0
  276.  
  277. void scale3(float a, float b, float c,
  278. long *ap, long *bp, long *cp)
  279. {
  280.     float maxim; /* integerize normal */
  281.  
  282.     maxim = (a > 0) ? a : -a; /* BUG IN BC 3.0 fabs()! */
  283.     maxim += (b > 0) ? b : -b;
  284.     maxim += (c > 0) ? c : -c;
  285.     if (maxim > 0.0001)
  286.     {
  287.         maxim /= LSCALE;
  288.         *ap = a/maxim;
  289.         *bp = b/maxim; /* normalize to <3.29> */
  290.         *cp = c/maxim;
  291.     }
  292. }
  293.  
  294. void scale4(float a, float b, float c, float d,
  295. long *ap, long *bp, long *cp, long *dp)
  296. {
  297.     float maxim; /* integerize normal */
  298.  
  299.     maxim = (a > 0) ? a : -a; /* BUG IN BC 3.0 fabs()! */
  300.     maxim += (b > 0) ? b : -b;
  301.     maxim += (c > 0) ? c : -c;
  302.     maxim += (d > 0) ? d : -d;
  303.     if (maxim > 0.0001)
  304.     {
  305.         maxim /= LSCALE;
  306.         *ap = a/maxim;
  307.         *bp = b/maxim; /* normalize to <3.29> */
  308.         *cp = c/maxim;
  309.         *dp = d/maxim;
  310.     }
  311. }
  312.  
  313.  
  314. /* facing normal, points should be in CW sequence */
  315. /* for axis aligned (+) split directions, use:    */
  316. /* x 0 0  x 100 0  x 0 100  for constant x */
  317. /* 0 y 0  0 y 100  100 y 0  for constant y */
  318. /* 0 0 z  100 0 z  0 100 z  for constant z */
  319.  
  320. void points_to_normal(float x1, float y1, float z1,
  321. float x2, float y2, float z2,
  322. float x3, float y3, float z3,
  323. long *ap, long *bp, long *cp)
  324. {
  325.     float v1x, v1y, v1z, v2x, v2y, v2z;
  326.     float a, b, c; /* compute line equation */
  327.  
  328.     v1x = x2 - x1;
  329.     v1y = y2 - y1;
  330.     v1z = z2 - z1;
  331.     v2x = x3 - x1;
  332.     v2y = y3 - y1;
  333.     v2z = z3 - y1;
  334.     a = (v1y * v2z - v2y * v1z);
  335.     b = (v1x * v2z - v2x * v1z);
  336.     c = (v1x * v2y - v2x * v1y);
  337.  
  338.     scale3(a, b, c, ap, bp, cp);
  339. }
  340.  
  341. void points_to_eqn(float x1, float y1, float z1,
  342. float x2, float y2, float z2,
  343. float x3, float y3, float z3,
  344. long *ap, long *bp, long *cp, long *dp)
  345. {
  346.     float v1x, v1y, v1z, v2x, v2y, v2z;
  347.     float a, b, c, d; /* compute line equation */
  348.  
  349.     v1x = x2 - x1;
  350.     v1y = y2 - y1;
  351.     v1z = z2 - z1;
  352.     v2x = x3 - x1;
  353.     v2y = y3 - y1;
  354.     v2z = z3 - y1;
  355.     a = (v1y * v2z - v2y * v1z);
  356.     b = (v1x * v2z - v2x * v1z);
  357.     c = (v1x * v2y - v2x * v1y);
  358.     d = -(a*x1 + b*y1 + c*z1); /* normalize to <3.29> */
  359.  
  360.     scale4(a, b, c, d, ap, bp, cp, dp);
  361. }
  362.  
  363. void normal_to_plane(float x, float y, float z,
  364. float nx, float ny, float nz,
  365. long *ap, long *bp, long *cp, long *dp)
  366. {
  367.     float a, b, c, d; /* compute line equation  */
  368.     /* given normal and point */
  369.     a = nx;
  370.     b = -ny;
  371.     c = nz;
  372.     d = -(a*x + b*y + c*z);
  373.  
  374.     scale4(a, b, c, d, ap, bp, cp, dp);
  375. }
  376.  
  377.  
  378. /************* WORLD AND CONFIG FILE LOADING **********/
  379.  
  380. NAMEREF *areas = NULL;
  381. NAMEREF *maps = NULL;
  382. NAMEREF *surfdefs = NULL;
  383. NAMEREF *objectlist = NULL;
  384. NAMEREF *fixedolist = NULL;
  385. NAMEREF *figurelist = NULL;
  386.  
  387. #ifdef ENABLE_STATEMACH
  388. extern NAMEREF *statelist;
  389. extern NAMEREF *varlist;
  390. #endif
  391.  
  392. void dump_lists(void)
  393. {
  394.     if(temp_mem) return; /* no need to delete if using temp. RAM */
  395.  
  396.     del_namelist(areas);
  397.     del_namelist(maps);
  398.     del_namelist(surfdefs);
  399.     del_namelist(objectlist);
  400.     del_namelist(fixedolist);
  401.     del_namelist(figurelist);
  402. #ifdef ENABLE_STATEMACH
  403.     del_namelist(statelist);
  404.     del_namelist(varlist);
  405. #endif
  406. }
  407.  
  408.  
  409. typedef struct _surface SURFACE;
  410.  
  411. struct _surface {
  412.     unsigned color;
  413.     char *value;
  414.     SURFACE *next;
  415. };
  416.  
  417. extern char loadpath[];
  418.  
  419. match(char *a, char *b)
  420. {
  421.     return !strnicmp(a, b, strlen(b));
  422. }
  423.  
  424. SEGMENT *find_seg(char *name)
  425. {
  426.     char *p = NULL;
  427.     OBJECT *o;
  428.     SEGMENT *s;
  429.  
  430.     if (name[0]==0) return NULL;
  431.     if ((p = strchr(name, '.')) == NULL)
  432.     {
  433.         if ((o = find_name(objectlist, name)) == NULL) goto try_seg;
  434.         p = get_object_owner(o);
  435.         return p;
  436.     }
  437.     else
  438.         {
  439.         *p++ = '\0';
  440. try_seg:
  441.         if ((s = find_name(figurelist, name)) == NULL) return NULL; /* no such figure */
  442.         if (p==NULL) return s; /* root of figure */
  443.         return find_segment_by_name(s, p);
  444.     }
  445. }
  446.  
  447.  
  448. void walk_segtree(SEGMENT *s, void (*f)());
  449. #ifdef FIGURE_MAPS
  450. static SURFACE *map_list = NULL;
  451.  
  452. void remap_fig(SEGMENT *s)
  453. {
  454.     int np;
  455.     SURFACE *p;
  456.     unsigned color;
  457.     void *v;
  458.     OBJECT *obj = seg_get_object(s);
  459.  
  460.     if(!obj) return;
  461.     get_obj_info(obj, NULL, &np);
  462.     while (np--)
  463.     {
  464.         get_poly_info(obj, np, &color, NULL, NULL, 0);
  465.         for (p = map_list; p; p = p->next)
  466.             if (p->color == color)
  467.             {
  468.                 if ((v = find_name(surfdefs, p->value)) != NULL)
  469.                     set_poly_color(obj, np, (unsigned) v);
  470.                 break;
  471.             }
  472.     }
  473. }
  474. #endif
  475.  
  476.  
  477. void clean_equals(char *b)
  478. {
  479.     char *c=b, *d=b;
  480.  
  481.     if(!strchr(b,'=')) return;
  482.  
  483.     while(*b) /* scan string: */
  484.     {
  485.         if(*b==' ' || *b=='\t') /* if whitespace: */
  486.         {
  487.             d = b; /* record start */
  488.             while (*b==' ' || *b=='\t') *c++ = *b++; /* copy till end of ws */
  489.             if(*b=='=')
  490.             {
  491.                 c = d; /* roll back position */
  492.                 *c++ = *b++; /* copy = */
  493.                 while (*b==' ' || *b=='\t') b++; /* skip trailing ws */
  494.             }
  495.         }
  496.         else *c++ = *b++;
  497.     }
  498.     *c = 0;
  499. }
  500.  
  501.  
  502. void tokstr(char *c)
  503. {
  504.     char *s = strtok(NULL, " \t,\n#");
  505.     if(s) sscanf(s, "%s",c);
  506. }
  507.  
  508. void tokstrn(char *c)
  509. {
  510.     char *s = strtok(NULL, " \t,\n#");
  511.     if(s) sscanf(s, "%s",c);
  512.     else *c = 0;
  513. }
  514.  
  515. void tokint(int *i)
  516. {
  517.     char *s = strtok(NULL, " \t,\n#");
  518.     if(s) sscanf(s, "%d",i);
  519. }
  520.  
  521. void tokhex(unsigned *i)
  522. {
  523.     char *s = strtok(NULL, " \t,\n#");
  524.     if(s) *i = (unsigned int)strtoul(s, NULL, 0);
  525. }
  526.  
  527. void toklong(long *i)
  528. {
  529.     char *s = strtok(NULL, " \t,\n#");
  530.     if(s) sscanf(s, "%ld",i);
  531. }
  532.  
  533. void tokfloat(float *i)
  534. {
  535.     char *s = strtok(NULL, " \t,\n#");
  536.     if(s) sscanf(s, "%f",i);
  537. }
  538.  
  539. void tokl16(long *i)
  540. {
  541.     float f;
  542.     char *s = strtok(NULL, " \t,\n#");
  543.     if(s)
  544.     {
  545.         sscanf(s, "%f", &f);
  546.         *i = 65536L * f;
  547.     }
  548. }
  549.  
  550. char *toks(void)
  551. {
  552.     char *s = strtok(NULL, " \t,\n#");
  553.     if (s) return "";
  554.     else return s;
  555. }
  556.  
  557. static int title_index = 0;
  558. char *title[25] = { 
  559.     NULL };
  560.  
  561.  
  562. static char *commands[] = {
  563.     "loadpath", "palette", "skycolor", "groundcolor", "screencolor",
  564.     "screenclear", "ambient", "worldscale", "flymode", "light",
  565.     "window", "key", "control", "viewframe", "start", "floormode",
  566.     "hither", "yon", "eyespacing", "screendist", "attachview",
  567.     "screenwidth", "convergence", "figure", "object", "stepsize",
  568.     "task", "position", "rotate", "camera", "options",
  569.     "include", "surfacemap", "surface", "surfacedef",
  570.     "split", "splitpt", "area", "floor", "floorpts",
  571.     "ceiling", "ceilingpts", "visfrom",
  572.     "endsplits", "polyobj", "polyobj2", "videodev",
  573.     "mousedev", "headdev", "glovedev", "ptrdev",
  574.     "switchdev", "glovecursor", "ptrcursor", "segaport", "switchport",
  575.     "pgloveport", "pglovetime", "stereoset", "stereotype",
  576.     "stereoleft", "stereoright", "depthtype", "attach", "detach",
  577.     "usemap", "fixedobj",
  578. #ifdef ENABLE_STATEMACH
  579.     "animation", "state", "if", "do",
  580. #endif
  581.     "title", "mlight", "segment", "addrep",
  582.     "anglestep",
  583. #ifdef ENABLE_ANIMATION
  584.     "pause", "frame", "savepcx",
  585. #endif
  586.     "version",
  587.     NULL
  588. };
  589.  
  590. enum com_codes {
  591.     c_loadpath = 0, c_palette, c_skycolor, c_groundcolor, c_screencolor,
  592.     c_screenclear, c_ambient, c_worldscale, c_flymode, c_light,
  593.     c_window, c_key, c_control, c_viewframe, c_start, c_floormode,
  594.     c_hither, c_yon, c_eyespacing, c_screendist, c_attachview,
  595.     c_screenwidth, c_convergence, c_figure, c_object, c_stepsize,
  596.     c_task, c_position, c_rotate, c_camera, c_options,
  597.     c_include, c_surfacemap, c_surface, c_surfacedef,
  598.     c_split, c_splitpt, c_area, c_floor, c_floorpts,
  599.     c_ceiling, c_ceilingpts, c_visfrom,
  600.     c_endsplits, c_polyobj, c_polyobj2, c_videodev,
  601.     c_mousedev, c_headdev, c_glovedev, c_ptrdev,
  602.     c_switchdev, c_glovecursor, c_ptrcursor, c_segaport, c_switchport,
  603.     c_pgloveport, c_pglovetime, c_stereoset, c_stereotype,
  604.     c_stereoleft, c_stereoright, c_depthtype, c_attach, c_detach,
  605.     c_usemap, c_fixedobj,
  606. #ifdef ENABLE_STATEMACH
  607.     c_animation, c_state, c_if, c_do,
  608. #endif
  609.     c_title, c_mlight, c_segment, c_addrep,
  610.     c_anglestep,
  611. #ifdef ENABLE_ANIMATION
  612.     c_pause, c_frame, c_savepcx,
  613. #endif
  614.     c_version,
  615. };
  616.  
  617.  
  618. static SURFACE *current_surface = NULL, *map;
  619. static SPLIT *current_split = NULL;
  620.  
  621. static char ps[] = " \t\n,#";
  622. static char st[] = "%s";
  623.  
  624. extern long spacestep, anglestep;
  625.  
  626. static int stop_it = 0; /* set non-zero if user hits a key during pause */
  627.  
  628. static int have_start = 0; /* non-zero if we've seen a "start" line */
  629.  
  630. static char default_map[100] = "";
  631.  
  632. read_world(FILE *in)
  633. {
  634.     char obuff[256];
  635.     char inbuff[256], *buff, fname[100];
  636.     char surfacemapname[100];
  637.     char *args;
  638.     char *pname;
  639.     int i,cmd;
  640.     while (fgets(inbuff, sizeof(inbuff), in))
  641.     {
  642. #ifdef ENCRYPT
  643.         if (buff[0] == 26) decrypt_buffer(inbuff);
  644. #endif
  645.         if (stop_it) {
  646.             stop_it = 0;
  647.             break;
  648.         }
  649.         strcpy(obuff,inbuff);
  650.         buff = strtok(inbuff,"#");
  651.         for (buff = inbuff; isspace(*buff); ++buff);
  652.         if(buff[0]==0) continue;
  653.         clean_equals(buff);
  654.         for (args = buff+1; isalpha(*args); ++args);
  655.         args++;
  656.         buff = strtok(buff," \t\n");
  657.  
  658.         for (cmd = 0; commands[cmd]; cmd++)
  659.             if (!stricmp(commands[cmd], buff)) break;
  660.         if (commands[cmd] == NULL) continue;
  661.  
  662.         switch(cmd)
  663.         {
  664.         case c_depthtype:
  665.             {
  666.             OBJECT *obj;
  667.             SEGMENT *s;
  668.             char oname[100];
  669.             unsigned dtype;
  670.             strcpy(oname, strtok(NULL,ps));
  671.             dtype = atoi(strtok(NULL, ps));
  672.             if ((s = find_seg(oname)) != NULL) { 
  673.                 obj = seg_get_object(s);
  674.                 if (obj)
  675.                     set_object_sorting(obj, dtype);                    
  676.                 }
  677.             }
  678.             break;
  679.         case c_attach:
  680.             {
  681.             SEGMENT *s, *par;
  682.             long tx, ty, tz, rx, ry, rz;
  683.             if ((s = find_seg(strtok(NULL,ps))) == NULL) break;
  684.             if ((par = find_seg(strtok(NULL,ps))) == NULL) break;
  685.             seg_getposang(s, &rx, &ry, &rz);
  686.             seg_getposxyz(s, &tx, &ty, &tz);
  687.             attach_segment(s, par);                    
  688.             abs_rot_segment(s, rx, ry, rz, RYXZ);
  689.             abs_move_segment(s, tx, ty, tz);
  690.             update_segment(s);
  691.             }
  692.             break;
  693.         case c_detach:
  694.             {
  695.             SEGMENT *s;
  696.             if ((s = find_seg(strtok(NULL, ps))) == NULL) break;
  697.             detach_segment(s);
  698.             update_segment(s);
  699.             }
  700.             break;
  701.         case c_usemap:
  702.             tokstrn(default_map);
  703.             break;
  704.         case c_version:
  705.             {
  706.             int ver = 4;
  707.             tokint(&ver);
  708.             if (ver > 5) {
  709.                 char tbuff[100];
  710.                 sprintf(tbuff, "Warning!  File is new version %d!", ver);
  711.                 if (running)
  712.                     popmsg(tbuff);
  713.                 else
  714.                     fprintf(stderr, "%s\n", tbuff);
  715.                 if (log_file)
  716.                     fprintf(log_file, "%s\n", tbuff);
  717.                 }
  718.             }
  719.             break;
  720. #ifdef ENABLE_ANIMATION
  721.         case c_frame:
  722.             {
  723.                 long f = 0L;
  724.                 if (!running) break; /* only valid while we're running */
  725.                 toklong(&f);
  726.                 if (f) frame_number = f;
  727.                 else ++frame_number;
  728.                 if (bioskey(1)) {
  729.                     unsigned key = getkey();
  730.                     if (toupper(key) == 'Q' || key == 0x1B) {
  731.                         popmsg("Stop animation?");
  732.                         if (toupper(getkey()) == 'Y') {
  733.                             stop_it = 1;
  734.                             break;
  735.                         }
  736.                     }
  737.                     else
  738.                         do_key(key);
  739.                 }
  740.                 refresh_display();
  741.                 if (key_wait) bioskey(0);
  742.                 if (frame_delay) delay(frame_delay);
  743.                 if (save_frames) {
  744.                     extern int v_page;
  745.                     char buff[100];
  746.                     FILE *out;
  747.                     sprintf(buff, pcx_pattern, frame_number);
  748.                     if ((out = fopen(buff, "wb")) == NULL)
  749.                         break;
  750.                     cursor_hide();
  751.                     save_pcx(out, v_page);
  752.                     cursor_show(v_page);
  753.                     fclose(out);
  754.                 }
  755.             }
  756.             break;
  757.         case c_pause:
  758.             {
  759.                 int nticks;
  760.                 char *message;
  761.                 if (!running) break; /* only valid while we're running */
  762.                 tokint(&nticks);
  763.                 message = strtok(NULL, "");
  764.                 refresh_display();
  765.                 if (message)
  766.                     popmsg(message);
  767.                 if (nticks)
  768.                     delay(nticks);
  769.                 else
  770.                     getkey();
  771.                 redraw = review = 1;
  772.             }
  773.             break;
  774.         case c_savepcx:
  775.             {
  776.                 extern int v_page;
  777.                 char buff[100], pattern[100];
  778.                 FILE *out;
  779.                 if (!running) break;
  780.                 tokstr(pattern);
  781.                 sprintf(buff, pattern, frame_number);
  782.                 if ((out = fopen(buff, "wb")) == NULL)
  783.                     break;
  784.                 else {
  785.                     char tbuff[100];
  786.                     sprintf(tbuff, "Could not open '%s'", buff);
  787.                     if (running)
  788.                         popmsg(tbuff);
  789.                     else
  790.                         fprintf(stderr, "%s\n", tbuff);
  791.                     if (log_file)
  792.                         fprintf(log_file, "%s\n", tbuff);
  793.                 }
  794.                 cursor_hide();
  795.                 save_pcx(out, v_page);
  796.                 cursor_show(v_page);
  797.                 fclose(out);
  798.             }
  799.             break;
  800. #endif
  801.         case c_stepsize:
  802.             toklong(&spacestep);
  803.             break;
  804.         case c_anglestep:
  805.             {
  806.             float a;
  807.             tokfloat(&a);
  808.             anglestep = a * 65536L;
  809.             }
  810.             break;
  811.         case c_loadpath:
  812.             tokstr(loadpath);
  813.             break;
  814.  
  815.         case c_options:
  816.             {
  817.                 char oss[100] = "";
  818.                 char *os = &oss[0];
  819.                 int i;
  820.                 extern int fancy_background, reflection_pool, show_logo, do_screen_clear;
  821.                 extern int show_location, show_compass, show_framerate, do_horizon;
  822.                 extern int use_BW, spinmode;
  823.                 tokstr(os);
  824.                 i = isupper(*os);
  825.                 while(*os)
  826.                 {
  827.                     switch(toupper(*os))
  828.                     {
  829.                     case 'C':
  830.                         show_compass = i; 
  831.                         break;
  832.                     case 'F':
  833.                         show_framerate = i; 
  834.                         break;
  835.                     case 'P':
  836.                         show_location = i; 
  837.                         break;
  838.                     case 'B':
  839.                         fancy_background = i; 
  840.                         break;
  841.                     case 'R':
  842.                         reflection_pool = i; 
  843.                         break;
  844.                     case 'M':
  845.                         use_BW = i; 
  846.                         break;
  847.                     case 'H':
  848.                         do_horizon = i;
  849.                         break;
  850.                     case 'A':
  851.                         old_angle_order = i;
  852.                         break;
  853.                     case 'S':
  854.                         spinmode = i;
  855.                         break;
  856.                     }
  857.                     os = os+1;
  858.                 }
  859.             }
  860.             break;
  861.  
  862.         case c_palette:
  863.             {
  864.                 FILE *in;
  865.                 char *f;
  866.                 tokstr(fname);
  867.                 if ((in = fopen(f = fix_fname(fname), "rb")) != NULL)
  868.                 {
  869.                     npalette = fread(palette, 3, 256, in);
  870.                     fclose(in);
  871.                 }
  872.                 else {
  873.                     char buff[100];
  874.                     sprintf(buff, "Could not open '%s'", f);
  875.                     if (running)
  876.                         popmsg(buff);
  877.                     else
  878.                         fprintf(stderr, "%s\n", buff);
  879.                     if (log_file)
  880.                         fprintf(log_file, "%s\n", buff);
  881.                 }
  882.             }
  883.             break;
  884.  
  885.         case c_skycolor:
  886.             tokhex(&sky_color);
  887.             break;
  888.         case c_groundcolor:
  889.             tokhex(&ground_color);
  890.             break;
  891.         case c_screencolor:
  892.             tokhex(&screen_clear_color);
  893.             break;
  894.         case c_screenclear:
  895.             tokint(&do_screen_clear);
  896.             break;
  897.         case c_flymode:
  898.             tokint(&flymode);
  899.             break;
  900.         case c_floormode:
  901.             tokint(&floormode);
  902.             break;
  903.         case c_ambient:
  904.             tokint(&(current_view->ambient));
  905.             break;
  906.         case c_worldscale:
  907.             default_stereo.world_scaling = 65536.0 * atof(strtok(NULL,ps));
  908.             break;
  909.         case c_light:
  910.             {
  911.             char *p;
  912.             default_view.lx = atol(strtok(NULL,ps));
  913.             default_view.ly = atol(strtok(NULL,ps));
  914.             default_view.lz = atol(strtok(NULL,ps));
  915.             p = strtok(NULL, ps);
  916.             if (isdigit(*p)) default_view.directional = atoi(p);
  917.             else default_view.directional = !stricmp(p, "spot");
  918.             }
  919.             break;
  920.         case c_mlight:
  921.             {
  922.                 extern int light2_i, light2_s;
  923.                 extern long light2_x, light2_y,light2_z;
  924.                 extern SEGMENT *light_seg, *light_seg2;
  925.                 char parent[100];
  926.                 char *m;
  927.                 SEGMENT *p_seg;
  928.                 long rx=0, ry=0, rz=0;
  929.                 if(light_seg) break; /* don't redo it */
  930.                 light2_x = atol(strtok(NULL,ps)); /* get position of pivot */
  931.                 light2_y = atol(strtok(NULL,ps));
  932.                 light2_z = atol(strtok(NULL,ps));
  933.                 m = strtok(NULL, ps);
  934.                 if (isdigit(*m)) default_view.directional = atoi(m);
  935.                 else default_view.directional = !stricmp(m, "spot");
  936.                 sscanf(strtok(NULL,ps), "%d", &light2_i); /* intensity*128 */
  937.                 tokstrn(parent);
  938.                 if(parent[0]==0 || !stricmp(parent, "fixed")) break; /* mobile pivot? */
  939.                 light_seg = new_seg(NULL);
  940.                 if ((m=strchr(parent, '='))!=NULL)
  941.                 {
  942.                     *m++ = 0;
  943.                     add_name(&figurelist, parent, light_seg); /* record name */
  944.                 }
  945.                 else m = parent;
  946.  
  947.                 p_seg = find_seg(m);
  948.                 if(p_seg)
  949.                 {
  950.                     attach_segment(light_seg, p_seg );
  951.                     abs_rot_segment(light_seg, rx, ry, rz, RYXZ);
  952.                     abs_move_segment(light_seg, light2_x, light2_y, light2_z);
  953.                     full_update_segment(p_seg);
  954.                 }
  955.                 else
  956.                 {
  957.                     abs_rot_segment(light_seg, rx, ry, rz, RYXZ);
  958.                     abs_move_segment(light_seg, light2_x, light2_y, light2_z);
  959.                     full_update_segment(light_seg);
  960.                 }
  961.                 break;
  962.             }
  963. #ifdef OLD
  964.         case c_light:
  965.             default_view.lx = atol(strtok(NULL,ps));
  966.             default_view.ly = atol(strtok(NULL,ps));
  967.             default_view.lz = atol(strtok(NULL,ps));
  968.             sscanf(strtok(NULL,ps), "%d", &(default_view.directional) );
  969.             break;
  970.         case c_mlight:
  971.             {
  972.                 extern int light2_i, light2_s;
  973.                 extern long light2_x, light2_y,light2_z;
  974.                 extern SEGMENT *light_seg, *light_seg2;
  975.                 char parent[100];
  976.                 char *m;
  977.                 SEGMENT *p_seg;
  978.                 long rx=0, ry=0, rz=0;
  979.  
  980.                 if(light_seg) break; /* don't redo it */
  981.                 light2_x = atol(strtok(NULL,ps)); /* get position of pivot */
  982.                 light2_y = atol(strtok(NULL,ps));
  983.                 light2_z = atol(strtok(NULL,ps));
  984.                 sscanf(strtok(NULL,ps), "%d", &light2_s); /* spotlight flag */
  985.                 sscanf(strtok(NULL,ps), "%d", &light2_i); /* intensity*128 */
  986.                 tokstrn(parent);
  987.                 if(parent[0]==0 || !stricmp(parent, "fixed")) break; /* mobile pivot? */
  988.                 light_seg = new_seg(NULL);
  989.                 if ((m=strchr(parent, '='))!=NULL)
  990.                 {
  991.                     *m++ = 0;
  992.                     add_name(&figurelist, parent, light_seg); /* record name */
  993.                 }
  994.                 else m = parent;
  995.  
  996.                 p_seg = find_seg(m);
  997.                 if(p_seg)
  998.                 {
  999.                     attach_segment(light_seg, p_seg );
  1000.                     abs_rot_segment(light_seg, rx, ry, rz, RYXZ);
  1001.                     abs_move_segment(light_seg, light2_x, light2_y, light2_z);
  1002.                     full_update_segment(p_seg);
  1003.                 }
  1004.                 else
  1005.                 {
  1006.                     abs_rot_segment(light_seg, rx, ry, rz, RYXZ);
  1007.                     abs_move_segment(light_seg, light2_x, light2_y, light2_z);
  1008.                     full_update_segment(light_seg);
  1009.                 }
  1010.                 break;
  1011.             }
  1012. #endif
  1013.         case c_window:
  1014.             {
  1015.                 int x, y, w, h;
  1016.  
  1017.                 switch (sscanf(strtok(NULL,""), "%d,%d,%d,%d", &x, &y, &w, &h))
  1018.                 {
  1019.                 case 4:
  1020.                     default_view.bottom = y + h - 1;
  1021.                 case 3:
  1022.                     default_view.right = x + w - 1;
  1023.                 case 2:
  1024.                     default_view.top = y;
  1025.                 case 1:
  1026.                     default_view.left = x;
  1027.                 default:
  1028.                     break;
  1029.                 };
  1030.             }
  1031.             break;
  1032.  
  1033.         case c_key:
  1034.             {
  1035.                 char fname[100];
  1036.                 unsigned key, param;
  1037.                 int i;
  1038.                 key = strtoul(strtok(NULL,ps), NULL, 0);
  1039.                 sscanf(strtok(NULL,ps), st, fname);
  1040.                 param = atoi(strtok(NULL,ps));
  1041.                 for (i = 0; functions[i].name; ++i)
  1042.                     if (!stricmp(fname, functions[i].name))
  1043.                     {
  1044.                         KEY *k;
  1045.                         if ((k = malloc(sizeof(KEY))) != NULL)
  1046.                         {
  1047.                             k->key = key;
  1048.                             k->param = param;
  1049.                             k->fn = functions[i].fn;
  1050.                             k->next = keylist;
  1051.                             keylist = k;
  1052.                         }
  1053.                         break;
  1054.                     }
  1055.             }
  1056.             break;
  1057.  
  1058.         case c_control:
  1059.             {
  1060.                 char fname[100];
  1061.                 int x, y, w, h;
  1062.                 unsigned mask, param;
  1063.                 int i;
  1064.  
  1065.                 x = atoi(strtok(NULL,ps));
  1066.                 y = atoi(strtok(NULL,ps));
  1067.                 w = atoi(strtok(NULL,ps));
  1068.                 h = atoi(strtok(NULL,ps));
  1069.                 mask = (unsigned)atol(strtok(NULL,ps));
  1070.                 sscanf(strtok(NULL,ps), st, fname);
  1071.                 param = (unsigned)atol(strtok(NULL,ps));
  1072.  
  1073.                 for (i = 0; functions[i].name; ++i)
  1074.                     if (!stricmp(fname, functions[i].name))
  1075.                     {
  1076.                         CONTROL *c;
  1077.                         if ((c = malloc(sizeof(CONTROL))) != NULL)
  1078.                         {
  1079.                             c->x = x;
  1080.                             c->y = y;
  1081.                             c->w = w;
  1082.                             c->h = h;
  1083.                             c->buttonmask = mask;
  1084.                             c->fn = functions[i].fn;
  1085.                             c->param = param;
  1086.                             c->next = controllist;
  1087.                             controllist = c;
  1088.                         }
  1089.                         break;
  1090.                     }
  1091.             }
  1092.             break;
  1093.  
  1094.         case c_viewframe:
  1095.             {
  1096.                 FILE *in;
  1097.                 sscanf(strtok(NULL,ps), st, framefname);
  1098.                 frame_x = atoi(strtok(NULL,ps));
  1099.                 frame_y = atoi(strtok(NULL,ps));
  1100.                 frame_w = atoi(strtok(NULL,ps));
  1101.                 frame_h = atoi(strtok(NULL,ps));
  1102.                 use_frame = 1;
  1103.             }
  1104.             break;
  1105.  
  1106.         case c_segment:
  1107.             {
  1108.                 SEGMENT *this_seg, *p_seg;
  1109.                 char parentname[60], *oname, *p;
  1110.                 long tx = 0, ty = 0, tz = 0, rx = 0, ry = 0, rz = 0;
  1111.                 ;
  1112.  
  1113.                 oname = NULL;
  1114.                 tokstrn(parentname);
  1115.                 tokl16(&rx);
  1116.                 tokl16(&ry);
  1117.                 tokl16(&rz);
  1118.                 toklong(&tx);
  1119.                 toklong(&ty);
  1120.                 toklong(&tz);
  1121.  
  1122.                 if ((p = strchr(parentname, '=')) != NULL)
  1123.                 {
  1124.                     oname = parentname;
  1125.                     *p++ = '\0';
  1126.                 }
  1127.                 else
  1128.                     p = parentname;
  1129.                 p_seg = find_seg(p);
  1130.                 if ((this_seg = new_seg(p_seg)) != NULL)
  1131.                 {
  1132.                     abs_move_segment(this_seg, tx, ty, tz);
  1133.                     abs_rot_segment(this_seg, rx, ry, rz, RYXZ);
  1134.                     full_update_segment(this_seg);
  1135.                     if (oname) add_name(&figurelist, oname, this_seg);
  1136.                 }
  1137.             }
  1138.             break;
  1139.  
  1140.         case c_start:
  1141.             have_start = 1;
  1142.             toklong(&default_view.ex);
  1143.             toklong(&default_view.ey);
  1144.             toklong(&default_view.ez);
  1145.             tokl16(&default_view.pan);
  1146.             tokl16(&default_view.tilt);
  1147.             tokl16(&default_view.roll);
  1148.             tokl16(&default_view.zoom);
  1149.             if(default_view.zoom<0.5*65536L) default_view.zoom = 0.5*65536L;
  1150.             break;
  1151.  
  1152.         case c_hither:
  1153.             default_view.hither = atol(strtok(NULL,ps));
  1154.             break;
  1155.         case c_yon:
  1156.             default_view.yon = atol(strtok(NULL,ps));
  1157.             break;
  1158.         case c_eyespacing:
  1159.             default_stereo.phys_eye_spacing = atol(strtok(NULL,ps));
  1160.             break;
  1161.         case c_screendist:
  1162.             default_stereo.phys_screen_dist = atol(strtok(NULL,ps));
  1163.             break;
  1164.         case c_screenwidth:
  1165.             default_stereo.phys_screen_width = atol(strtok(NULL,ps));
  1166.             default_stereo.pixel_width = atoi(strtok(NULL,ps));
  1167.             break;
  1168.         case c_convergence:
  1169.             default_stereo.phys_convergence = atol(strtok(NULL,ps));
  1170.             break;
  1171.         case c_attachview:
  1172.             {
  1173.                 SEGMENT *p_seg;
  1174.                 char parentname[60];
  1175.                 tokstrn(parentname);
  1176.                 preconnect_view_seg = find_seg(parentname);
  1177.             }
  1178.             break;
  1179.  
  1180.         case c_figure:
  1181.             {
  1182.                 char filename[60], parentname[60], *oname, *p;
  1183. #ifdef FIGURE_MAPS
  1184.                 char mappings[60];
  1185. #endif
  1186.                 float sx = 1, sy = 1, sz = 1, rx = 0, ry = 0, rz = 0;
  1187.                 long tx = 0, ty = 0, tz = 0;
  1188.                 FILE *fig;
  1189.                 parentname[0] = '\0';
  1190. #ifdef FIGURE_MAPS
  1191.                 mappings[0] = '\0';
  1192. #endif
  1193.                 oname = NULL;
  1194.  
  1195.                 sscanf(strtok(NULL,ps), st, filename);
  1196.                 tokfloat(&sx);
  1197.                 tokfloat(&sy);
  1198.                 tokfloat(&sz);
  1199.                 tokfloat(&rx);
  1200.                 tokfloat(&ry);
  1201.                 tokfloat(&rz);
  1202.                 toklong(&tx);
  1203.                 toklong(&ty);
  1204.                 toklong(&tz);
  1205.                 tokstrn(parentname);
  1206. #ifdef FIGURE_MAPS
  1207.                 tokstrn(mappings);
  1208.  
  1209.                 map_list = find_name(maps, mappings);
  1210. #endif
  1211.                 add_ext(filename, "fig");
  1212.                 set_readseg_scale(sx, sy, sz);
  1213.                 if ((p = strchr(filename, '=')) != NULL)
  1214.                 {
  1215.                     oname = filename;
  1216.                     *p++ = '\0';
  1217.                 }
  1218.                 else
  1219.                     p = filename;
  1220.                 if ((fig = fopen(pname = fix_fname(p), "r")) != NULL)
  1221.                 {
  1222.                     SEGMENT *this_seg, *p_seg;
  1223.                     p_seg = find_seg(parentname);
  1224.                     set_readseg_objlist(objlist);
  1225.                     readseg_err = 0;
  1226.                     if ((this_seg = readseg(fig, p_seg)) != NULL)
  1227.                     {
  1228.                         abs_move_segment(this_seg, tx, ty, tz);
  1229.                         abs_rot_segment(this_seg, rx*65536L, ry*65536L, rz*65536L, RYXZ);
  1230.                         update_segment(this_seg);
  1231.                     }
  1232.                     fclose(fig);
  1233.                     if (readseg_err) {
  1234.                         if (running)
  1235.                             popmsg(readseg_errmsgs[-readseg_err]);
  1236.                         else
  1237.                             fprintf(stderr, "%s in figure file '%s'\n", readseg_errmsgs[-readseg_err], pname);
  1238.                         if (log_file)
  1239.                             fprintf(log_file, "%s in figure file '%s'\n", readseg_errmsgs[-readseg_err], pname); 
  1240.                     }
  1241. #ifdef FIGURE_MAPS
  1242.                     if(map_list) walk_segtree(this_seg, remap_fig);
  1243. #endif
  1244.                     if (oname) add_name(&figurelist, oname, this_seg);
  1245.                 }
  1246.                 else {
  1247.                     char buff[100];
  1248.                     sprintf(buff, "Could not open '%s'", pname);
  1249.                     if (running)
  1250.                         popmsg(buff);
  1251.                     else
  1252.                         fprintf(stderr, "%s\n", buff);
  1253.                     if (log_file)
  1254.                         fprintf(log_file, "%s\n", buff);
  1255.                 }
  1256.             }
  1257.             break;
  1258.  
  1259.         case c_fixedobj:
  1260.         case c_object:
  1261.             {
  1262.                 char mappings[100], *p, filename[100], *oname, parentname[100];
  1263.                 float sx = 1, sy = 1, sz = 1, rx = 0, ry = 0, rz = 0;
  1264.                 long tx = 0, ty = 0, tz = 0;
  1265.                 int dt = 0;
  1266.                 MATRIX m;
  1267.                 FILE *plg;
  1268.                 OBJECT *obj;
  1269.  
  1270.                 sscanf(strtok(NULL,ps), st, filename);
  1271.                 tokfloat(&sx);
  1272.                 tokfloat(&sy);
  1273.                 tokfloat(&sz);
  1274.                 tokfloat(&rx);
  1275.                 tokfloat(&ry);
  1276.                 tokfloat(&rz);
  1277.                 toklong(&tx);
  1278.                 toklong(&ty);
  1279.                 toklong(&tz);
  1280.                 tokint(&dt);
  1281.                 tokstrn(mappings);
  1282.                 tokstrn(parentname);
  1283.                 if (cmd == c_fixedobj)
  1284.                     strcpy(parentname, "fixed");
  1285.                 add_ext(filename, "plg");
  1286.                 set_loadplg_scale(sx, sy, sz);
  1287.                 set_loadplg_depthsort(dt);
  1288.  
  1289.                 map = find_name(maps, mappings);
  1290.                 if (!map)
  1291.                     map = find_name(maps, default_map);
  1292.  
  1293.                 if ((p = strchr(filename, '=')) != NULL)
  1294.                 {
  1295.                     oname = filename;
  1296.                     *p++ = '\0';
  1297.                 }
  1298.                 else
  1299.                 {
  1300.                     oname = NULL;
  1301.                     p = filename;
  1302.                 }
  1303.                 if ((plg = fopen(pname = fix_fname(p), "r")) != NULL)
  1304.                 {
  1305.                     while ((obj = load_multi_plg(plg)) != NULL)
  1306.                         if (obj)
  1307.                         {
  1308.                             if (map)
  1309.                             {
  1310.                                 int np;
  1311.  
  1312.                                 get_obj_info(obj, NULL, &np);
  1313.                                 while (np--)
  1314.                                 {
  1315.                                     SURFACE *p;
  1316.                                     unsigned color;
  1317.                                     void *v;
  1318.  
  1319.                                     get_poly_info(obj, np, &color, NULL, NULL, 0);
  1320.                                     for (p = map; p; p = p->next)
  1321.                                         if (p->color == color)
  1322.                                         {
  1323.                                             if ((v = find_name(surfdefs, p->value)) != NULL)
  1324.                                                 set_poly_color(obj, np, (unsigned) v);
  1325.                                             break;
  1326.                                         }
  1327.                                 }
  1328.                             }
  1329.  
  1330.                             if (oname)
  1331.                                 if (stricmp(parentname, "fixed")) add_name(&objectlist, oname, obj);
  1332.                                 else add_name(&fixedolist, oname, obj);
  1333.                             oname = NULL; /* so it's done once only */
  1334.  
  1335.                             if (!stricmp(parentname, "fixed"))
  1336.                             {
  1337.                                 std_matrix(m, (long) (rx * 65536L), (long) (ry * 65536L),
  1338.                                 (long) (rz * 65536L), tx, ty, tz);
  1339.                                 apply_matrix(obj, m);
  1340.                                 if (current_split)
  1341.                                     add_obj_to_split_center(current_split, obj);
  1342.                                 else
  1343.                                     add_obj_to_split_area(split_tree, obj);
  1344.                             }
  1345.                             else
  1346.                                 {
  1347.                                 SEGMENT *s, *p = NULL;
  1348.  
  1349.                                 p = find_seg(parentname);
  1350.                                 s = new_seg(p);
  1351.                                 seg_set_object(s, obj);
  1352.                                 set_object_owner(obj, s);
  1353.                                 abs_rot_segment(s, rx * 65536L, ry * 65536L, rz * 65536L, RYXZ);
  1354.                                 abs_move_segment(s, tx, ty, tz);
  1355.                                 update_segment(s);
  1356.                             }
  1357.                         }
  1358.                     if (load_err) {
  1359.                         if (running)
  1360.                             popmsg(plg_errmsgs[-load_err]);
  1361.                         else
  1362.                             fprintf(stderr, "%s on line %d of file %s\n", plg_errmsgs[-load_err], err_line, pname);
  1363.                         if (log_file)
  1364.                             fprintf(log_file, "%s on line %d of file %s\n", plg_errmsgs[-load_err], err_line, pname);
  1365.                     }
  1366.                 }
  1367.                 else {
  1368.                     char buff[100];
  1369.                     sprintf(buff, "Could not open '%s'", pname);
  1370.                     if (running)
  1371.                         popmsg(buff);
  1372.                     else
  1373.                         fprintf(stderr, "%s\n", buff);
  1374.                     if (log_file)
  1375.                         fprintf(log_file, "%s\n", buff);
  1376.                 }
  1377.                 fclose(plg);
  1378.             }
  1379.             break;
  1380.  
  1381.         case c_addrep:
  1382.             {
  1383.                 char mappings[100], *p, filename[100], *oname;
  1384.                 float sx = 1, sy = 1, sz = 1, rx = 0, ry = 0, rz = 0;
  1385.                 long tx = 0, ty = 0, tz = 0;
  1386.                 int defsize = 0;
  1387.                 MATRIX m;
  1388.                 FILE *plg;
  1389.                 OBJECT *obj, sobj;
  1390.                 SEGMENT *s;
  1391.  
  1392.                 sscanf(strtok(NULL,ps), st, filename);
  1393.                 tokfloat(&sx);
  1394.                 tokfloat(&sy);
  1395.                 tokfloat(&sz);
  1396.                 tokfloat(&rx);
  1397.                 tokfloat(&ry);
  1398.                 tokfloat(&rz);
  1399.                 toklong(&tx);
  1400.                 toklong(&ty);
  1401.                 toklong(&tz);
  1402.                 tokint(&defsize);
  1403.                 tokstrn(mappings);
  1404.  
  1405.                 add_ext(filename, "plg");
  1406.                 set_loadplg_scale(sx, sy, sz);
  1407.                 map = find_name(maps, mappings);
  1408.  
  1409.                 if ((p = strchr(filename, '=')) == NULL) break;
  1410.                 oname = filename;
  1411.                 *p++ = '\0';
  1412.                 if((s = find_seg(oname))!=NULL)
  1413.                 {
  1414.                     if(!(obj = seg_get_object(s))) break;
  1415.                 }
  1416.                 else
  1417.                     {
  1418.                     if(!(obj = find_name(fixedolist, oname))) break;
  1419.                 }
  1420.  
  1421.                 std_matrix(m, (long) (rx * 65536L), (long) (ry * 65536L),
  1422.                 (long) (rz * 65536L), tx, ty, tz);
  1423.                 if ((plg = fopen(pname = fix_fname(p), "r")) != NULL)
  1424.                 {
  1425.                     while ((obj = load_extra_rep(plg, obj, defsize)) != NULL)
  1426.                         if (obj)
  1427.                         {
  1428.                             apply_matrix(obj, m);
  1429.                             copy_world_to_object(obj);
  1430.                             compute_obj(obj);
  1431.                             if (map)
  1432.                             {
  1433.                                 int np;
  1434.  
  1435.                                 get_obj_info(obj, NULL, &np);
  1436.                                 while (np--)
  1437.                                 {
  1438.                                     SURFACE *p;
  1439.                                     unsigned color;
  1440.                                     void *v;
  1441.                                     get_poly_info(obj, np, &color, NULL, NULL, 0);
  1442.                                     for (p = map; p; p = p->next)
  1443.                                         if (p->color == color)
  1444.                                         {
  1445.                                             if ((v = find_name(surfdefs, p->value)) != NULL)
  1446.                                                 set_poly_color(obj, np, (unsigned) v);
  1447.                                             break;
  1448.                                         }
  1449.                                 }
  1450.                             }
  1451.                         }
  1452.                     if (load_err && log_file)
  1453.                         fprintf(log_file, "%s on line %d of file %s\n", plg_errmsgs[-load_err], err_line, pname);
  1454.                 }
  1455.                 else {
  1456.                     char buff[100];
  1457.                     sprintf(buff, "Could not open '%s'", pname);
  1458.                     if (running)
  1459.                         popmsg(buff);
  1460.                     else
  1461.                         fprintf(stderr, "%s\n", buff);
  1462.                     if (log_file)
  1463.                         fprintf(log_file, "%s\n", buff);
  1464.                 }
  1465.                 fclose(plg);
  1466.                 full_update_segment(s); /* update world sphere coords */
  1467.             }
  1468.             break;
  1469.  
  1470.         case c_task:
  1471.             {
  1472.                 char taskname[100], param[100];
  1473.                 long period;
  1474.                 int i;
  1475.                 void *data;
  1476.  
  1477.                 sscanf(strtok(NULL,ps), st, taskname);
  1478.                 period = atol(strtok(NULL,ps));
  1479.                 strcpy(param, strtok(NULL,"\n"));
  1480.                 for (i = 0; functions[i].name; ++i)
  1481.                     if (!stricmp(taskname, functions[i].name)) {
  1482.                         add_task(&tasklist, functions[i].fn, period, param);
  1483.                         break;
  1484.                     }
  1485.             }
  1486.             break;
  1487.  
  1488.         case c_position:
  1489.             {
  1490.                 OBJECT *obj;
  1491.                 SEGMENT *s;
  1492.                 char oname[100];
  1493.                 long x, y, z;
  1494.  
  1495.                 strcpy(oname, strtok(NULL,ps));
  1496.                 x = atol(strtok(NULL,ps));
  1497.                 y = atol(strtok(NULL,ps));
  1498.                 z = atol(strtok(NULL,ps));
  1499.                 if ((s = find_seg(oname)) != NULL) { 
  1500.                     obj = seg_get_object(s);
  1501.                     abs_move_segment(s, x, y, z);
  1502.                     update_segment(s);
  1503.                     if (obj) {
  1504.                         remove_from_objlist(obj);
  1505.                         add_obj_to_split_area(split_tree, obj);
  1506.                     }
  1507.                 }
  1508.             }
  1509.             break;
  1510.  
  1511.         case c_rotate:
  1512.             {
  1513.                 OBJECT *obj;
  1514.                 SEGMENT *s;
  1515.                 char oname[100];
  1516.                 float rx, ry, rz;
  1517.  
  1518.                 strcpy(oname,strtok(NULL,ps));
  1519.                 rx = atof(strtok(NULL,ps));
  1520.                 ry = atof(strtok(NULL,ps));
  1521.                 rz = atof(strtok(NULL,ps));
  1522.                 if ((s = find_seg(oname)) != NULL)
  1523.                 {
  1524.                     abs_rot_segment(s, rx * 65536L, ry * 65536L, rz * 65536L, RYXZ);
  1525.                     update_segment(s);
  1526.                 }
  1527.             }
  1528.             break;
  1529.  
  1530.         case c_camera:
  1531.             {
  1532.                 int n;
  1533.                 char *c;
  1534.                 extern VIEW *all_views[], *save_views[];
  1535.                 VIEW *v, *bv;
  1536.  
  1537.                 tokint(&n);
  1538.                 if (n < 1 || n > 10) break;
  1539.                 if (all_views[n-1] == NULL)
  1540.                     all_views[n-1] = (VIEW *) malloc(sizeof(VIEW));
  1541.                 v = all_views[n-1];
  1542.                 *v = default_view;
  1543.                 toklong(&(v->ex));
  1544.                 toklong(&(v->ey));
  1545.                 toklong(&(v->ez));
  1546.                 if (old_angle_order) {
  1547.                     tokl16(&(v->pan));
  1548.                     tokl16(&(v->tilt));
  1549.                     }
  1550.                 else {
  1551.                     tokl16(&(v->tilt));
  1552.                     tokl16(&(v->pan));
  1553.                     }
  1554.                 tokl16(&(v->roll));
  1555.                 tokl16(&(v->zoom));
  1556.                 toklong(&(v->hither));
  1557.                 toklong(&(v->yon));
  1558.                 bv = save_views[n-1] = (VIEW *) malloc(sizeof(VIEW));
  1559.                 *bv = *v;
  1560.                 save_views[n-1] = bv; /* save "home" copy */
  1561.                 if (!have_start && n == 1) { /* if no start line yet, camera 1 is start */
  1562.                     default_view = *v;
  1563.                     if (default_view.zoom < 0.5*65536L) default_view.zoom = 0.5*65536L;
  1564.                 }
  1565.             }
  1566.             break;
  1567.  
  1568.         case c_include:
  1569.             {
  1570.                 char fname[100];
  1571.                 FILE *in;
  1572.                 char *f;
  1573.                 strcpy(fname,strtok(NULL,ps));
  1574.                 if ((in = fopen(f = fix_fname(fname), "r")) != NULL)
  1575.                 {
  1576.                     read_world(in);
  1577.                     fclose(in);
  1578.                 }
  1579.                 else {
  1580.                     char buff[100];
  1581.                     sprintf(buff, "Could not open '%s'", f);
  1582.                     if (running)
  1583.                         popmsg(buff);
  1584.                     else
  1585.                         fprintf(stderr, "%s\n", buff);
  1586.                     if (log_file)
  1587.                         fprintf(log_file, "%s\n", buff);
  1588.                 }
  1589.             }
  1590.             break;
  1591.  
  1592.         case c_surfacemap:
  1593.             {
  1594.                 /* starts a new map of color numbers to surface names */
  1595.                 strcpy(surfacemapname,strtok(NULL,ps));
  1596.                 current_surface = NULL;
  1597.             }
  1598.             break;
  1599.  
  1600.         case c_surface:
  1601.             {
  1602.                 SURFACE *p;
  1603.                 /* maps a color number to a surface name */
  1604.                 if ((p = malloc(sizeof(SURFACE))) != NULL) {
  1605.                     char buf2[40];
  1606.                     if (current_surface == NULL)
  1607.                         add_name(&maps, surfacemapname, p);
  1608.                     else
  1609.                         current_surface->next = p;
  1610.                     current_surface = p;
  1611.                     p->next = NULL;
  1612.                     p->color = strtoul(strtok(NULL,ps), NULL, 0);
  1613.                     strcpy(buf2,strtok(NULL,ps));
  1614.                     p->value = strdup(buf2);
  1615.                 }
  1616.             }
  1617.             break;
  1618.  
  1619.         case c_surfacedef:
  1620.             {
  1621.                 char sname[100], svalue[20];
  1622.                 /* maps a surface name to an internal color value */
  1623.                 strcpy(sname,strtok(NULL,ps));
  1624.                 strcpy(svalue,strtok(NULL,ps));
  1625.                 add_name(&surfdefs, sname, (void *) convert_color(svalue, NULL));
  1626.             }
  1627.             break;
  1628.  
  1629.         case c_split:
  1630.             {
  1631.                 float x, y, z, nnx, nny, nnz;
  1632.                 long nx, ny, nz;
  1633.                 unsigned flags = 0;
  1634.  
  1635.                 set_move_handler(split_move_handler);
  1636.                 set_global_split_root(&split_tree);
  1637.                 x = atof(strtok(NULL,ps));
  1638.                 y = atof(strtok(NULL,ps));
  1639.                 z = atof(strtok(NULL,ps));
  1640.                 nnx = atof(strtok(NULL,ps));
  1641.                 nny = atof(strtok(NULL,ps));
  1642.                 nnz = atof(strtok(NULL,ps));
  1643.                 tokhex(&flags);
  1644.                 scale3(nnx, nny, nnz, &nx, &ny, &nz);
  1645.                 current_split = add_split(&split_tree, x, y, z, nx, ny, nz, flags);
  1646.             }
  1647.             break;
  1648.  
  1649.         case c_splitpt:
  1650.             {
  1651.                 float x1, x2, x3, y1, y2, y3, z1, z2, z3;
  1652.                 long nx, ny, nz;
  1653.                 unsigned flags = 0;
  1654.  
  1655.                 set_move_handler(split_move_handler);
  1656.                 set_global_split_root(&split_tree);
  1657.                 x1 = atof(strtok(NULL,ps));
  1658.                 y1 = atof(strtok(NULL,ps));
  1659.                 z1 = atof(strtok(NULL,ps));
  1660.                 x2 = atof(strtok(NULL,ps));
  1661.                 y2 = atof(strtok(NULL,ps));
  1662.                 z2 = atof(strtok(NULL,ps));
  1663.                 x3 = atof(strtok(NULL,ps));
  1664.                 y3 = atof(strtok(NULL,ps));
  1665.                 z3 = atof(strtok(NULL,ps));
  1666.                 flags = strtoul(strtok(NULL,ps), NULL, 0);
  1667.                 points_to_normal(x1, y1, z1, x2, y2, z2, x3, y3, z3, &nx, &ny, &nz);
  1668.                 current_split = add_split(&split_tree, x1, y1, z1, nx, ny, nz, flags);
  1669.             }
  1670.             break;
  1671.  
  1672.         case c_area:
  1673.             {
  1674.                 long x, y, z;
  1675.                 void *what_area();
  1676.                 char areaname[100];
  1677.                 AREA *a;
  1678.  
  1679.                 x = atol(strtok(NULL,ps));
  1680.                 y = atol(strtok(NULL,ps));
  1681.                 z = atol(strtok(NULL,ps));
  1682.                 sscanf(strtok(NULL,ps), st, areaname);
  1683.                 add_name(&areas, areaname, a=what_area(split_tree, x, y, z));
  1684.                 set_area_name(a, areaname);
  1685.             }
  1686.             break;
  1687.  
  1688.         case c_floor:
  1689.             {
  1690.                 char aname[100];
  1691.                 float aa, bb, cc, dd;
  1692.                 long a,b,c,d;
  1693.  
  1694.                 sscanf(strtok(NULL,ps), st, aname);
  1695.                 aa = atof(strtok(NULL,ps));
  1696.                 bb = atof(strtok(NULL,ps));
  1697.                 cc = atof(strtok(NULL,ps));
  1698.                 dd = atof(strtok(NULL,ps));
  1699.                 scale4(aa, bb, cc, dd, &a, &b, &c, &d);
  1700.                 add_floor(find_name(areas, aname), a, b, c, d);
  1701.             }
  1702.             break;
  1703.  
  1704.         case c_floorpts:
  1705.             {
  1706.                 char aname[100];
  1707.                 float x1, y1, z1, x2, y2, z2, x3, y3, z3;
  1708.                 long a, b, c, d;
  1709.  
  1710.                 sscanf(strtok(NULL,ps), st, aname);
  1711.                 x1 = atof(strtok(NULL,ps));
  1712.                 y1 = atof(strtok(NULL,ps));
  1713.                 z1 = atof(strtok(NULL,ps));
  1714.                 x2 = atof(strtok(NULL,ps));
  1715.                 y2 = atof(strtok(NULL,ps));
  1716.                 z2 = atof(strtok(NULL,ps));
  1717.                 x3 = atof(strtok(NULL,ps));
  1718.                 y3 = atof(strtok(NULL,ps));
  1719.                 z3 = atof(strtok(NULL,ps));
  1720.                 points_to_eqn(x1, y1, z1, x2, y2, z2, x3, y3, z3, &a, &b, &c, &d);
  1721.                 add_floor(find_name(areas, aname), a, b, c, d);
  1722.             }
  1723.             break;
  1724.  
  1725.         case c_ceiling:
  1726.             {
  1727.                 char aname[100];
  1728.                 float aa, bb, cc, dd;
  1729.                 long a, b, c, d;
  1730.  
  1731.                 sscanf(strtok(NULL,ps), st, aname);
  1732.                 aa = atof(strtok(NULL,ps));
  1733.                 bb = atof(strtok(NULL,ps));
  1734.                 cc = atof(strtok(NULL,ps));
  1735.                 dd = atof(strtok(NULL,ps));
  1736.                 scale4(aa, bb, cc, dd, &a, &b, &c, &d);
  1737.                 add_ceiling(find_name(areas, aname), a, b, c, d);
  1738.             }
  1739.             break;
  1740.  
  1741.         case c_ceilingpts:
  1742.             {
  1743.                 char aname[100];
  1744.                 float x1, y1, z1, x2, y2, z2, x3, y3, z3;
  1745.                 long a, b, c, d;
  1746.  
  1747.                 sscanf(strtok(NULL,ps), st, aname);
  1748.                 x1 = atof(strtok(NULL,ps));
  1749.                 y1 = atof(strtok(NULL,ps));
  1750.                 z1 = atof(strtok(NULL,ps));
  1751.                 x2 = atof(strtok(NULL,ps));
  1752.                 y2 = atof(strtok(NULL,ps));
  1753.                 z2 = atof(strtok(NULL,ps));
  1754.                 x3 = atof(strtok(NULL,ps));
  1755.                 y3 = atof(strtok(NULL,ps));
  1756.                 z3 = atof(strtok(NULL,ps));
  1757.                 points_to_eqn(x1, y1, z1, x2, y2, z2, x3, y3, z3, &a, &b, &c, &d);
  1758.                 add_ceiling(find_name(areas, aname), a, b, c, d);
  1759.             }
  1760.             break;
  1761.  
  1762.         case c_visfrom:
  1763.             {
  1764.                 char aname[100], alist[100], *p;
  1765.                 AREA *a, *b;
  1766.  
  1767.                 sscanf(strtok(NULL,ps), st, aname);
  1768.                 if ((a = find_name(areas, aname)) != NULL)
  1769.                     for (p = strtok(NULL, ", "); p; p = strtok(NULL, ", "))
  1770.                         if ((b = find_name(areas, p)) != NULL)
  1771.                             add_visfrom(a, b);
  1772.             }
  1773.             break;
  1774.  
  1775.         case c_endsplits:
  1776.             current_split = NULL;
  1777.             break;
  1778.  
  1779.         case c_polyobj:
  1780.         case c_polyobj2:
  1781.             {
  1782.                 char map[100], map2[100];
  1783.                 OBJECT *obj;
  1784.                 POLY *poly;
  1785.                 unsigned color;
  1786.                 int nv = 0;
  1787.                 int i;
  1788.                 long x[18], y[18], z[18];
  1789.  
  1790.                 map[0] = '\0';
  1791.                 set_loadplg_depthsort(0);
  1792.                 nv = atoi(strtok(NULL,ps));
  1793.                 tokstrn(map);
  1794.                 if (cmd==c_polyobj2) tokstrn(map2);
  1795.  
  1796.                 if (nv > 18) nv = 18;
  1797.                 for(i=0;i<nv;i++)
  1798.                 {
  1799.                     x[i] = atol(strtok(NULL,ps));
  1800.                     y[i] = atol(strtok(NULL,ps));
  1801.                     z[i] = atol(strtok(NULL,ps));
  1802.                 }
  1803.  
  1804.                 obj = new_obj(0, nv, (cmd==c_polyobj2) ? 2 : 1);
  1805.                 if (obj)
  1806.                 {
  1807.                     char *p;
  1808.                     if ((p = strtok(NULL, ps)) != NULL)
  1809.                         set_object_sorting(obj, atoi(p));
  1810.                     if (map)
  1811.                         color = (unsigned) find_color(surfdefs, map);
  1812.                     poly = add_poly(obj, color, nv);
  1813.                     for (i = 0; i < nv; i++)
  1814.                     {
  1815.                         add_vertex(obj, x[i], y[i], z[i]);
  1816.                         add_point(obj, poly, nv-i-1);
  1817.                     }
  1818.                     if (cmd == c_polyobj2)
  1819.                     {
  1820.                         if (map2)
  1821.                             color = (unsigned) find_color(surfdefs, map2);
  1822.                         poly = add_poly(obj, color, nv);
  1823.                         for (i = 0; i < nv; i++)
  1824.                         {
  1825.                             add_point(obj, poly, i);
  1826.                         }
  1827.                     }
  1828.                     compute_all_obj(obj);
  1829.                     if (current_split)
  1830.                         add_obj_to_split_center(current_split, obj);
  1831.                     else
  1832.                         add_obj_to_split_area(split_tree, obj);
  1833.                 }
  1834.             }
  1835.             break;
  1836.  
  1837.             /* CONFIG FILE LOAD STUFF */
  1838.  
  1839.             /* THESE DONE AFTER LOADING */
  1840.  
  1841.         case c_videodev:
  1842.             {
  1843.                 extern char vdname[];
  1844.                 extern int vdmode;
  1845.  
  1846.                 sscanf(args, "%s %x", vdname, &vdmode);
  1847.             }
  1848.             break;
  1849.  
  1850.         case c_mousedev:
  1851.             {
  1852.                 extern char mdname[];
  1853.  
  1854.                 sscanf(args, st, mdname);
  1855.             }
  1856.             break;
  1857.  
  1858.         case c_headdev:
  1859.             {
  1860.                 extern char hdname[];
  1861.                 extern float hdo_x, hdo_y, hdo_z, hdo_rx, hdo_ry, hdo_rz;
  1862.  
  1863.                 sscanf(args, "%s %f %f %f %f %f %f", hdname,
  1864.                           &hdo_x, &hdo_y, &hdo_z,
  1865.                           &hdo_rx, &hdo_ry, &hdo_rz);
  1866.             }
  1867.             break;
  1868.  
  1869.         case c_glovedev:
  1870.             {
  1871.                 extern char gpdname[];
  1872.                 extern int have_glove;
  1873.                 extern float gpdo_x, gpdo_y, gpdo_z, gpdo_rx, gpdo_ry, gpdo_rz;
  1874.  
  1875.                 have_glove = 1;
  1876.                 sscanf(args, "%s %f %f %f %f %f %f", gpdname, &gpdo_x, &gpdo_y, &gpdo_z, &gpdo_rx, &gpdo_ry, &gpdo_rz);
  1877.             }
  1878.             break;
  1879.  
  1880.         case c_ptrdev:
  1881.             {
  1882.                 extern char gpdname[];
  1883.                 extern int have_ptr;
  1884.                 extern float gpdo_x, gpdo_y, gpdo_z, gpdo_rx, gpdo_ry, gpdo_rz;
  1885.  
  1886.                 have_ptr = 1;
  1887.                 sscanf(args, "%s %f %f %f %f %f %f", gpdname, &gpdo_x, &gpdo_y, &gpdo_z, &gpdo_rx, &gpdo_ry, &gpdo_rz);
  1888.             }
  1889.             break;
  1890.  
  1891.         case c_switchdev:
  1892.             {
  1893.                 extern char swdname[];
  1894.                 sscanf(args, st, swdname);
  1895.             }
  1896.             break;
  1897.  
  1898.         case c_glovecursor:
  1899.             {
  1900.                 extern char gpcursor[];
  1901.                 sscanf(args, st, gpcursor);
  1902.             }
  1903.             break;
  1904.  
  1905.         case c_ptrcursor:
  1906.             {
  1907.                 extern char gpcursor[];
  1908.                 sscanf(args, st, gpcursor);
  1909.             }
  1910.             break;
  1911.  
  1912.             /* CONFIG: DONE IMMEDIATELY */
  1913.  
  1914.         case c_switchport:  /* synonym with no trademark problems */
  1915.         case c_segaport:
  1916.             {
  1917.                 sscanf(args, "%x %x %x %x %x", &sega_address,
  1918.                 &sega_mask, &sega_left, &sega_right, &sega_doff, &sega_port_image);
  1919.             }
  1920.             break;
  1921.  
  1922.         case c_pgloveport:
  1923.             {
  1924.                 sscanf(args, "%x %x %x %x %x %x %x %x", &glove_in_port, &glove_out_port,
  1925.                 &glove_write_mask, &glove_none_mask, &glove_latch_mask, &glove_clock_mask,
  1926.                 &glove_clock_latch, &glove_data_mask, &port_image );
  1927.             }
  1928.             break;
  1929.  
  1930.         case c_pglovetime:
  1931.             {
  1932.                 sscanf(args, "%d %d", &glove_bit_delay, &glove_byte_delay );
  1933.             }
  1934.             break;
  1935.  
  1936.         case c_stereoset:
  1937.             {
  1938.                 float ws = 1.0;
  1939.  
  1940.                 sscanf(args, "%ld %ld %ld %ld %ld %f", &(default_stereo.phys_screen_dist),
  1941.                 &(default_stereo.phys_screen_width), &(default_stereo.pixel_width),
  1942.                 &(default_stereo.phys_eye_spacing), &(default_stereo.phys_convergence), &ws);
  1943.                 default_stereo.world_scaling = 65536.0 * ws;
  1944.             }
  1945.             break;
  1946.  
  1947.         case c_stereotype:
  1948.             {
  1949.                 char sty[80];
  1950.                 extern int stereo_type;
  1951.  
  1952.                 sscanf(args, st, sty);
  1953.                 if (match(sty, "OFF")) stereo_type = MONOSCOPIC;
  1954.                 else if (match(sty, "SWITCH")) stereo_type = SWITCHED;
  1955.                 else if (match(sty, "SEPARATE")) stereo_type = SEPARATE;
  1956.                 else if (match(sty, "SPLIT")) stereo_type = SPLITLR;
  1957.             }
  1958.             break;
  1959.  
  1960.         case c_stereoleft:
  1961.             {
  1962.                 sl_left = -1;
  1963.                 sscanf(args, "%d %d %f %ld %ld %ld %ld %ld", &sl_xoff, &sl_xflip,
  1964.                 &sl_xrot, &sl_left, &sl_top, &sl_right, &sl_bottom );
  1965.             }
  1966.             break;
  1967.  
  1968.         case c_stereoright:
  1969.             {
  1970.                 sr_left = -1;
  1971.                 sscanf(args, "%d %d %f %ld %ld %ld %ld %ld", & sr_xoff, &sr_xflip,
  1972.                 &sr_xrot, &sr_left, &sr_top, &sr_right, &sr_bottom ) ;
  1973.             }
  1974.             break;
  1975.  
  1976.             /* ANIMATION PARSER */
  1977.  
  1978. #ifdef ENABLE_STATEMACH
  1979.         case c_animation:
  1980.             parse_ani(); 
  1981.             break;
  1982.         case c_state:
  1983.             parse_state(); 
  1984.             break;
  1985.         case c_if:
  1986.             parse_if(); 
  1987.             break;
  1988.         case c_do:
  1989.             parse_do(); 
  1990.             break;
  1991. #endif
  1992.  
  1993.         case c_title:
  1994.             if((args!=NULL)&&(args[0]!=0)&&(title_index<22))
  1995.             {
  1996.                 char s[200];
  1997.                 sscanf(args, "%s", s);
  1998.                 if(strlen(args)>36) args[36] = 0;
  1999.                 if(!stricmp(s,"memory"))
  2000.                 {
  2001.                     sprintf(s, "Memory Left: %ld", coreleft());
  2002.                     args = s;
  2003.                 }
  2004.                 title[title_index++] = strdup(args);
  2005.                 title[title_index] = NULL;
  2006.             }
  2007.             break;
  2008.  
  2009.         }
  2010.  
  2011.     }
  2012.     return 0;
  2013. }
  2014.  
  2015. static void dump_segment(SEGMENT *s, char *prefix, FILE *out)
  2016. {
  2017.     SEGMENT *p;
  2018.     char *name;
  2019.     long x, y, z;
  2020.     if ((name = seg_getname(s)) != NULL) {
  2021.         seg_getjointxyz(s, &x, &y, &z);
  2022.         fprintf(out, "position %s.%s %ld %ld %ld\n", prefix, name, x, y, z);
  2023.         seg_getjointang(s, &x, &y, &z);
  2024.         fprintf(out, "rotate %s.%s %f %f %f\n", prefix, name, x/65536.0, y/65536.0, z/65536.0);
  2025.     }
  2026.     for (p = child_segment(s); p; p = sibling_segment(p))
  2027.         dump_segment(p, prefix, out);
  2028. }
  2029.  
  2030. #ifdef ENABLE_STATE_SAVELOAD
  2031. int save_state(void) /* write world state to a .wld file */
  2032. {
  2033.     extern VIEW *all_views[];
  2034.     VIEW *v;
  2035.     char fn[20];
  2036.     FILE *out;
  2037.     OBJECT *obj; 
  2038.     SEGMENT *seg;
  2039.     NAMEREF *p;
  2040.     char *name;
  2041.     int i;
  2042.     askfor("Filename? ", fn, 15);
  2043.     if (fn[0] == '\0') return -1;
  2044.     if ((out = fopen(fn, "a")) == NULL) {
  2045.         popmsg("Could not write to file!");
  2046.         getkey();
  2047.         return -2;
  2048.     }
  2049.     fprintf(out, "\nframe\n");
  2050.     fprintf(out, "ambient %d\n", current_view->ambient);
  2051.     for (i = 0; i < 10; ++i)
  2052.         if (old_angle_order) {
  2053.             if ((v = all_views[i]) != NULL)
  2054.                 fprintf(out, "camera %d %ld %ld %ld %f %f %f %f\n", i + 1,
  2055.                 v->ex, v->ey, v->ez,
  2056.                 v->pan/65536.0, v->tilt/65536.0, v->roll/65536.0,
  2057.                 v->zoom/65536.0);
  2058.             }
  2059.         else {
  2060.             if ((v = all_views[i]) != NULL)
  2061.                 fprintf(out, "camera %d %ld %ld %ld %f %f %f %f\n", i + 1,
  2062.                 v->ex, v->ey, v->ez,
  2063.                 v->tilt/65536.0, v->pan/65536.0, v->roll/65536.0,
  2064.                 v->zoom/65536.0);
  2065.             }
  2066. #ifdef NOPE
  2067.     if ((v = all_views[0]) != NULL)
  2068.         fprintf(out, "start %ld %ld %ld %f %f %f %f\n",
  2069.         v->ex, v->ey, v->ez,
  2070.         v->pan/65536.0, v->tilt/65536.0, v->roll/65536.0,
  2071.         v->zoom/65536.0);
  2072. #endif
  2073.     for (p = objectlist; p; p = p->next)
  2074.         if ((seg = get_object_owner(p->value)) != NULL) {
  2075.             long x, y, z;
  2076.             seg_getjointxyz(seg, &x, &y, &z);
  2077.             fprintf(out, "position %s %ld %ld %ld\n", p->name, x, y, z);
  2078.             seg_getjointang(seg, &x, &y, &z);
  2079.             fprintf(out, "rotate %s %f %f %f\n", p->name, x/65536.0, y/65536.0, z/65536.0);
  2080.         }
  2081.     for (p = figurelist; p; p = p->next)
  2082.         dump_segment(p->value, p->name, out);
  2083.     fclose(out); 
  2084.     return 0;
  2085. }
  2086.  
  2087. int load_state(void)
  2088. {
  2089.     char buff[500];
  2090.     FILE *in;
  2091.     long start_frame = 0;
  2092.     askfor("File? ", buff, 15);
  2093.     if (buff[0] == '\0') return -1;
  2094.     add_ext(buff, "wld");
  2095.     if ((in = fopen(buff, "r")) == NULL) {
  2096.         popmsg("Could not open file");
  2097.         getkey();
  2098.         return -2;
  2099.     }
  2100.     refresh_display();
  2101.     askfor("Start frame [1]? ", buff, 15);
  2102.     start_frame = atol(buff);
  2103.     refresh_display();
  2104.     askfor("millisecs/frame [zero]? ", buff, 8);
  2105.     frame_delay = atoi(buff);
  2106.     refresh_display();
  2107.     popmsg("Wait for key?");
  2108.     key_wait = toupper(getkey()) == 'Y';
  2109.     refresh_display();
  2110.     popmsg("Save frames?");
  2111.     if (toupper(getkey()) == 'Y') {
  2112.         save_frames = 1;
  2113.         refresh_display();
  2114.         askfor("Pattern? ", pcx_pattern, 15);
  2115.     }
  2116.     else
  2117.         save_frames = 0;
  2118.     refresh_display();
  2119.     if (start_frame) {
  2120.         long pos = ftell(in);
  2121.         while (fgets(buff, sizeof(buff), in)) {
  2122.             if (!strnicmp(strtok(buff, " \t"), "frame", 5)) {
  2123.                 long f;
  2124.                 toklong(&f);
  2125.                 if (f >= start_frame) {
  2126.                     fseek(in, pos, SEEK_SET);
  2127.                     break;
  2128.                 }
  2129.             }
  2130.             pos = ftell(in);
  2131.         }
  2132.     }
  2133.     return read_world(in);
  2134. }
  2135. #endif
  2136.