home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / source / t3dlib_src_r43.lha / writeim.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-05  |  30.3 KB  |  1,146 lines

  1. /* writeim.c - write an Imagine 2.0 TDDD (3D Data Decription) FILE
  2.  *           - by traversing the TTDDDLIB database
  3.  *           - written by Glenn M. Lewis - 3/27/92
  4.  *           - Altered for Imagine 3.0 - Rob Hounsell - Sept 94
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include <ctype.h>
  9. #include "t3dlib.h"
  10. #ifdef __STDC__
  11. #include <stdlib.h>
  12. #include <strings.h>
  13. #include "writeim_protos.h"
  14. #endif
  15. #include <sys/types.h>
  16. #include <sys/stat.h>
  17.  
  18. #ifdef AZTEC_C
  19. #include <fcntl.h>
  20. #include <exec/types.h>
  21. #endif
  22.  
  23. static void process_INFO();
  24. static void process_OBJ();
  25. static void process_EXTR();
  26. static void process_DESC();
  27. static void process_ISTG();        /* Imagine staging FILE */
  28.  
  29. /* Here are a few necessary utilities */
  30.  
  31. static void put_name(world, name, size)
  32. WORLD *world;
  33. register char  *name;
  34. register int size;
  35. {
  36.     while (*name && size) {
  37.         fputc(*name++, world->inp);
  38.         size--;
  39.     }
  40.     while (size--) fputc(0, world->inp);    /* Pad the rest of the string w/ 0 */
  41. }
  42.  
  43. static void put_UBYTE(world, u)
  44. WORLD *world;
  45. UBYTE u;
  46. {
  47.     fputc((char)u, world->inp);
  48. }
  49.  
  50. static void put_UWORD(world, w)
  51. WORLD *world;
  52. UWORD w;
  53. {
  54.     put_UBYTE(world, (UBYTE)(w>>8));
  55.     put_UBYTE(world, (UBYTE)(w&0xFF));
  56. }
  57.  
  58. static void put_ULONG(world, l)
  59. WORLD *world;
  60. ULONG l;
  61. {
  62.     put_UWORD(world, (UWORD)(l>>16));
  63.     put_UWORD(world, (UWORD)(l&0xFFFF));
  64. }
  65.  
  66. static void put_FRACT(world, f)
  67. WORLD *world;
  68. double f;
  69. {
  70.     put_ULONG(world, (ULONG)(f*65536.0));
  71. }
  72.  
  73. static void put_XYZ(world, st)            /* Write a common string */
  74. WORLD *world;
  75. XYZ_st *st;
  76. {
  77.     put_FRACT(world, st->x);
  78.     put_FRACT(world, st->y);
  79.     put_FRACT(world, st->z);
  80. }
  81.  
  82. static void put_RGB(world, st)            /* Write a common string */
  83. WORLD *world;
  84. RGB_st *st;
  85. {
  86.     put_UBYTE(world, 0);    /* PAD */
  87.     put_UBYTE(world, st->r);
  88.     put_UBYTE(world, st->g);
  89.     put_UBYTE(world, st->b);
  90. }
  91.  
  92. static void write_size(world, pos)
  93. WORLD *world;
  94. long pos;
  95. {
  96.     long size;
  97.     long cur = ftell(world->inp);
  98.     size = cur-pos;
  99.     if (size&1) { size++; put_UBYTE(world, (UBYTE)0); }
  100.     fseek(world->inp, pos-4L, 0);
  101.     put_ULONG(world, (ULONG)size);
  102.     fseek(world->inp, cur, 0);
  103. }
  104.  
  105. /********************/
  106. /* The MAIN section */
  107. /********************/
  108.  
  109. int write_TDDD(world, myFILE)
  110. WORLD *world;
  111. FILE *myFILE;
  112. {
  113.     long pos, pos2;
  114.     OBJECT *obj;
  115.     struct stat statbuf;
  116. #ifdef AMIGA
  117.     int x;
  118. #endif
  119.  
  120.     if (!world || !myFILE) return(0);
  121.     world->inp = myFILE;
  122.  
  123.     if (world->info || world->object) {
  124.         /* Don't write TDDD if there is nothing to write */
  125.  
  126.         /* Start the IFF TDDD FILE */
  127.         put_name(world, "FORM", 4);
  128.         put_ULONG(world, 0L);        /* Fill this in later [seek(,4L,0)] */
  129.         pos = ftell(world->inp);    /* Save where this starting position is */
  130.         put_name(world, "TDDD", 4);
  131.  
  132.         if (world->info) process_INFO(world, world->info);
  133.         for (obj = world->object; obj; obj=obj->next) {
  134.             put_name(world, "OBJ ", 4);
  135.             put_ULONG(world, 0L);
  136.             pos2 = ftell(world->inp);    /* Save for later */
  137.             process_OBJ(world, obj);
  138.             write_size(world, pos2);
  139.         }
  140.         write_size(world, pos);
  141.  
  142.     /* All done.  Close up shop. */
  143.         fclose(world->inp);
  144.     }
  145.  
  146. /* Also write the staging FILE if we have staging information */
  147.     if (!world->istg) return(1);
  148.  
  149.     /* Check is the staging FILE already exists */
  150.     if (stat("staging", &statbuf)==0) {
  151.         fprintf(stderr, "WARNING: Moving existing 'staging' file to 'staging.bak'.\n");
  152. #ifdef AMIGA
  153.         /* We can only assume this will wait until process completes */
  154.         x = system("copy staging staging.bak");
  155.         if (x != 0) fprintf(stderr, "ERROR:  Staging FILE copy failed\n");
  156. #else
  157.         system("mv staging staging.bak");
  158.         wait(1);
  159. #endif
  160.     }
  161.  
  162.     if (!(world->inp = fopen("staging", "w"))) {
  163.         fprintf(stderr, "WARNING: Could not open 'staging' FILE for output.\n");
  164.         fprintf(stderr, "No staging information saved!\n");
  165.         world->inp = myFILE;
  166.         return(1);
  167.     }
  168.  
  169.     /* Output the staging file... */
  170.     /* Start the IFF ISTG file */
  171.     put_name(world, "FORM", 4);
  172.     put_ULONG(world, 0L);            /* Fill this in later [seek(,4L,0)] */
  173.     pos = ftell(world->inp);        /* Save where this starting position is */
  174.     put_name(world, "ISTG", 4);
  175.     process_ISTG(world);
  176.     write_size(world, pos);
  177.  
  178.     /* Return the FILE pointer back to normal... */
  179.     fclose(world->inp);
  180.     world->inp = myFILE;
  181.     return(1);
  182. }
  183.  
  184. static void process_INFO(world, info)
  185. WORLD *world;
  186. INFO *info;
  187. {
  188.     register ULONG i;
  189.     long pos;
  190.  
  191.     put_name(world, "INFO", 4);
  192.     put_ULONG(world, 0L);
  193.     pos = ftell(world->inp);    /* Save for later */
  194.  
  195.     for (i=0; i<8; i++)
  196.         if (info->brsh[i][0]) {
  197.             put_name(world, "BRSH", 4);
  198.             put_ULONG(world, 82L);
  199.             put_UWORD(world, (UWORD)i);
  200.             put_name(world, info->brsh[i], 80);
  201.         }
  202.  
  203.     for (i=0; i<8; i++)
  204.         if (info->stnc[i][0]) {
  205.             put_name(world, "STNC", 4);
  206.             put_ULONG(world, 82L);
  207.             put_UWORD(world, (UWORD)i);
  208.             put_name(world, info->stnc[i], 80);
  209.         }
  210.  
  211.     for (i=0; i<8; i++)
  212.         if (info->txtr[i][0]) {
  213.             put_name(world, "TXTR", 4);
  214.             put_ULONG(world, 82L);
  215.             put_UWORD(world, (UWORD)i);
  216.             put_name(world, info->txtr[i], 80);
  217.         }
  218.  
  219.     if (info->otrk[0]) {
  220.         put_name(world, "OTRK", 4);
  221.         put_ULONG(world, 18L);
  222.         put_name(world, info->otrk, 18);
  223.     }
  224.  
  225.     if (info->ambi) {
  226.         put_name(world, "AMBI", 4);
  227.         put_ULONG(world, 4L);
  228.         put_RGB(world, info->ambi);
  229.     }
  230.  
  231.     if (info->obsv) {
  232.         put_name(world, "OBSV", 4);
  233.         put_ULONG(world, 28L);
  234.         put_XYZ(world, &info->obsv->came);
  235.         put_XYZ(world, &info->obsv->rota);
  236.         put_FRACT(world, info->obsv->foca);
  237.     }
  238.  
  239.     if (info->ostr) {
  240.         put_name(world, "OSTR", 4);
  241.         put_ULONG(world, 56L);
  242.         put_name(world, info->ostr->path, 18);
  243.         put_XYZ(world, &info->ostr->tran);
  244.         put_XYZ(world, &info->ostr->rota);
  245.         put_XYZ(world, &info->ostr->scal);
  246.         put_UWORD(world, info->ostr->info);
  247.     }
  248.  
  249.     if (info->fade) {
  250.         put_name(world, "FADE", 4);
  251.         put_ULONG(world, 12L);
  252.         put_FRACT(world, info->fade->at);
  253.         put_FRACT(world, info->fade->by);
  254.         put_RGB(world, &info->fade->to);
  255.     }
  256.  
  257.     if (info->skyc) {
  258.         put_name(world, "SKYC", 4);
  259.         put_ULONG(world, 8L);
  260.         put_RGB(world, &info->skyc->hori);
  261.         put_RGB(world, &info->skyc->zeni);
  262.     }
  263.  
  264.     if (info->glb0) {
  265.         put_name(world, "GLB0", 4);
  266.         put_ULONG(world, 8L);
  267.         for (i=0; i<8; i++)
  268.             put_UBYTE(world, (UBYTE)info->glb0[i]);
  269.     }
  270.     write_size(world, pos);
  271. }
  272.  
  273. static void process_OBJ(world, obj)
  274. WORLD *world;
  275. OBJECT *obj;
  276. {
  277.     OBJECT *o;
  278.  
  279.     if (obj->extr) process_EXTR(world, obj);
  280.     else process_DESC(world, obj);
  281.  
  282.     for (o=obj->child; o; o=o->next)
  283.         process_OBJ(world, o);
  284.  
  285.     put_name(world, "TOBJ", 4);
  286.     put_ULONG(world, 0L);
  287. }
  288.  
  289. static void process_EXTR(world, obj)
  290. WORLD *world;
  291. OBJECT *obj;
  292. {
  293.     long pos;
  294.  
  295.     put_name(world, "EXTR", 4);
  296.     put_ULONG(world, 0L);
  297.     pos = ftell(world->inp);    /* Save for later */
  298.  
  299.     put_name(world, "LOAD", 4);
  300.     put_ULONG(world, 80L);
  301.     put_name(world, obj->extr->filename, 80);
  302.  
  303.     put_name(world, "MTRX", 4);
  304.     put_ULONG(world, 60L);
  305.     put_XYZ(world, &obj->extr->mtrx.tran);
  306.     put_XYZ(world, &obj->extr->mtrx.scal);
  307.     put_XYZ(world, &obj->extr->mtrx.rota1);
  308.     put_XYZ(world, &obj->extr->mtrx.rota2);
  309.     put_XYZ(world, &obj->extr->mtrx.rota3);
  310.  
  311.     write_size(world, pos);
  312. }
  313.  
  314. static void process_DESC(world, obj)
  315. WORLD *world;
  316. OBJECT *obj;
  317. {
  318.     register int i, j;
  319.     register DESC *desc;
  320.     FGRP *fgrp;
  321.     long pos;
  322.  
  323.     if (!obj) return;
  324.     desc = obj->desc;
  325.     if (!desc) return;
  326.  
  327.     put_name(world, "DESC", 4);
  328.     put_ULONG(world, 0L);
  329.     pos = ftell(world->inp);    /* Save for later */
  330.  
  331.     if (desc->name) {
  332.         put_name(world, "NAME", 4);
  333.         put_ULONG(world, 18L);
  334.         put_name(world, desc->name, 18);
  335.     }
  336.  
  337.     if (desc->posi) {
  338.         put_name(world, "POSI", 4);
  339.         put_ULONG(world, 12L);
  340.         put_XYZ(world, desc->posi);
  341.     }
  342.  
  343.     if (desc->size) {
  344.         put_name(world, "SIZE", 4);
  345.         put_ULONG(world, 12L);
  346.         put_XYZ(world, desc->size);
  347.     }
  348.  
  349.     if (desc->colr) {
  350.         put_name(world, "COLR", 4);
  351.         put_ULONG(world, 4L);
  352.         put_RGB(world, desc->colr);
  353.     }
  354.  
  355.     if (desc->refl) {
  356.         put_name(world, "REFL", 4);
  357.         put_ULONG(world, 4L);
  358.         put_RGB(world, desc->refl);
  359.     }
  360.  
  361.     if (desc->tran) {
  362.         put_name(world, "TRAN", 4);
  363.         put_ULONG(world, 4L);
  364.         put_RGB(world, desc->tran);
  365.     }
  366.  
  367.     if (desc->spc1) {
  368.         put_name(world, "SPC1", 4);
  369.         put_ULONG(world, 4L);
  370.         put_RGB(world, desc->spc1);
  371.     }
  372.  
  373.     if (desc->ints) {
  374.         put_name(world, "INTS", 4);
  375.         put_ULONG(world, 4L);
  376.         put_FRACT(world, (*desc->ints));
  377.     }
  378.  
  379.     /* Mandatory field... stuff it, regardless */
  380.     if (desc->shap) {
  381.         put_name(world, "SHAP", 4);
  382.         put_ULONG(world, 4L);
  383.         put_UWORD(world, (UWORD)desc->shap[0]);
  384.         put_UWORD(world, (UWORD)desc->shap[1]);
  385.     } else {
  386.         put_name(world, "SHAP", 4);
  387.         put_ULONG(world, 4L);
  388.         put_UWORD(world, (UWORD)2);
  389.         put_UWORD(world, (UWORD)1);
  390.     }
  391.  
  392.     if (desc->axis) {
  393.         put_name(world, "AXIS", 4);
  394.         put_ULONG(world, 36L);
  395.         put_XYZ(world, &desc->axis->xaxi);
  396.         put_XYZ(world, &desc->axis->yaxi);
  397.         put_XYZ(world, &desc->axis->zaxi);
  398.     }
  399.  
  400.     if (desc->tpar) {
  401.         put_name(world, "TPAR", 4);
  402.         put_ULONG(world, 64L);
  403.         for (i=0; i<16; i++) put_FRACT(world, desc->tpar[i]);
  404.     }
  405.  
  406.     if (desc->surf) {
  407.         put_name(world, "SURF", 4);
  408.         put_ULONG(world, 5L);
  409.         for (i=0; i<5; i++) put_UBYTE(world, desc->surf[i]);
  410.         put_UBYTE(world, (UBYTE)0);    /* To make this chunk even-sized */
  411.     }
  412.  
  413.     if (desc->mttr) {
  414.         put_name(world, "MTTR", 4);
  415.         put_ULONG(world, 2L);
  416.         put_UBYTE(world, desc->mttr->type);
  417.         put_UBYTE(world, (UBYTE)(((int)((desc->mttr->indx-1.0)*100.0))&0xFF));
  418.     }
  419.  
  420.     if (desc->spec) {
  421.         put_name(world, "SPEC", 4);
  422.         put_ULONG(world, 2L);
  423.         put_UBYTE(world, desc->spec[0]);
  424.         put_UBYTE(world, desc->spec[1]);
  425.     }
  426.  
  427.     if (desc->prp0) {
  428.         put_name(world, "PRP0", 4);
  429.         put_ULONG(world, 6L);
  430.         for (i=0; i<6; i++) put_UBYTE(world, desc->prp0[i]);
  431.     }
  432.  
  433.     if (desc->prp1) {
  434.         put_name(world, "PRP1", 4);
  435.         put_ULONG(world, 8L);
  436.         for (i=0; i<8; i++) put_UBYTE(world, desc->prp1[i]);
  437.     }
  438.  
  439.     if (desc->stry) {
  440.         put_name(world, "STRY", 4);
  441.         put_ULONG(world, 56L);
  442.         put_name(world, desc->stry->path, 18);
  443.         put_XYZ(world, &desc->stry->tran);
  444.         put_XYZ(world, &desc->stry->rota);
  445.         put_XYZ(world, &desc->stry->scal);
  446.         put_UWORD(world, desc->stry->info);
  447.     }
  448.  
  449.     if (desc->pcount) {
  450.         put_name(world, "PNTS", 4);
  451.         put_ULONG(world, (ULONG)desc->pcount*12L+2L);
  452.         put_UWORD(world, desc->pcount);
  453.         for (i=0; i<desc->pcount; i++)
  454.             put_XYZ(world, &desc->pnts[i]);
  455.     }
  456.  
  457.     if (desc->ecount) {
  458.         put_name(world, "EDGE", 4);
  459.         put_ULONG(world, (ULONG)desc->ecount*4L+2L);
  460.         put_UWORD(world, desc->ecount);
  461.         for (i=0; i<2*desc->ecount; i++)
  462.             put_UWORD(world, desc->edge[i]);
  463.     }
  464.  
  465.     if (desc->eflg) {
  466.         put_name(world, "EFLG", 4);
  467.         put_ULONG(world, (ULONG)desc->eflg->num+2L);
  468.         put_UWORD(world, desc->eflg->num);
  469.         for (i=0; i<desc->eflg->num; i++)
  470.             put_UBYTE(world, desc->eflg->eflg[i]);
  471.         if (desc->eflg->num&1) put_UBYTE(world, 0);    /* Pad on even boundary */
  472.     }
  473.  
  474.     if (desc->fcount) {
  475.         put_name(world, "FACE", 4);
  476.         put_ULONG(world, (ULONG)desc->fcount*6L+2L);
  477.         put_UWORD(world, desc->fcount);
  478.         for (i=0; i<3*desc->fcount; i++)
  479.             put_UWORD(world, desc->face[i]);
  480.  
  481.         if (desc->clst) {
  482.             put_name(world, "CLST", 4);
  483.             put_ULONG(world, (ULONG)desc->fcount*3L+2L);
  484.             put_UWORD(world, desc->fcount);
  485.             for (i=0; i<3*desc->fcount; i++)
  486.                 put_UBYTE(world, desc->clst[i]);
  487.             if (desc->fcount&1) put_UBYTE(world, 0);    /* Pad to even length */
  488.         }
  489.         if (desc->rlst) {
  490.             put_name(world, "RLST", 4);
  491.             put_ULONG(world, (ULONG)desc->fcount*3L+2L);
  492.             put_UWORD(world, desc->fcount);
  493.             for (i=0; i<3*desc->fcount; i++)
  494.                 put_UBYTE(world, desc->rlst[i]);
  495.             if (desc->fcount&1) put_UBYTE(world, 0);    /* Pad to even length */
  496.         }
  497.         if (desc->tlst) {
  498.             put_name(world, "TLST", 4);
  499.             put_ULONG(world, (ULONG)desc->fcount*3L+2L);
  500.             put_UWORD(world, desc->fcount);
  501.             for (i=0; i<3*desc->fcount; i++)
  502.                 put_UBYTE(world, desc->tlst[i]);
  503.             if (desc->fcount&1) put_UBYTE(world, 0);    /* Pad to even length */
  504.         }
  505.     }
  506.  
  507.     for (fgrp=desc->fgrp; fgrp; fgrp=fgrp->next) {
  508.         put_name(world, "FGRP", 4);
  509.         put_ULONG(world, (ULONG)fgrp->num*2L+2L+18L);
  510.         put_UWORD(world, fgrp->num);
  511.         put_name(world, fgrp->name, 18);
  512.         for (i=0; i<fgrp->num; i++)
  513.             put_UWORD(world, fgrp->face[i]);
  514.     }
  515.  
  516.     for (i=0; i<4; i++) {
  517.         if (!desc->txt2[i]) continue;
  518.         put_name(world, "TXT2", 4);
  519.         j = strlen(desc->txt2[i]->Name);
  520. /* CWC */    j = 144L+17L+j;  /* Oddly enough, an odd number is allowed here */
  521. /* CWC         put_ULONG(world, 94L+18L+j+(1-(j&1)));    original line */
  522. /* CWC */    put_ULONG(world, j);
  523.         put_UWORD(world, desc->txt2[i]->Flags);
  524.         put_XYZ(world, &desc->txt2[i]->TAxis.tran);
  525.         put_XYZ(world, &desc->txt2[i]->TAxis.rota1);
  526.         put_XYZ(world, &desc->txt2[i]->TAxis.rota2);
  527.         put_XYZ(world, &desc->txt2[i]->TAxis.rota3);
  528.         put_XYZ(world, &desc->txt2[i]->TAxis.scal);
  529.         for (j = 0; j < 16; j++) put_FRACT(world, desc->txt2[i]->Params[j]);
  530.         for (j = 0; j < 16; j++) put_UBYTE(world, desc->txt2[i]->PFlags[j]);
  531. /* CWC        put_name(world, desc->txt2[i]->SubName, 18); original line */
  532. /* CWC */    put_name(world, desc->txt2[i]->SubName, 17);  /* Yes, this 
  533.                                                                  is correct! */
  534.         j = strlen(desc->txt2[i]->Name);
  535.         put_UWORD(world, j);
  536.         put_name(world, desc->txt2[i]->Name, j);
  537. /* CWC */       j = j + 144L + 17L;
  538.         if (j&1) put_UBYTE(world, 0);    /* Pad the odd byte */
  539.     }
  540.  
  541.     write_size(world, pos);
  542. }
  543.  
  544. /************************************************************************/
  545. /* New code to write staging FILE - written by Glenn M. Lewis - 8/11/92 */
  546. /* Altered for Imagine 3.0 - Rob Hounsell - Sept 94                     */
  547. /************************************************************************/
  548.  
  549. static void process_OSZ2();
  550. static void process_OSIZ();
  551. static void process_POS2();
  552. static void process_POSN();
  553. static void process_ALN2();
  554. static void process_ALGN();
  555. static void process_ASSC();
  556. static void process_HING();
  557. static void process_LYR0();
  558. static void process_GLB3();
  559. static void process_GLB2();
  560. static void process_AXIS();
  561. static void process_LIT2();
  562. static void process_LITE();
  563. static void process_FIL3();
  564. static void process_FILE();
  565. static void process_SPFX();
  566.  
  567. static void process_ISTG(world)
  568. WORLD *world;
  569. {
  570.     register ISTG *istg = world->istg;
  571.     register SOBJ *sobj;
  572.     long pos2;
  573.  
  574.     if (!world->inp) return;    /* File not open */
  575.  
  576.     put_name(world, "MAXF", 4);
  577.     put_ULONG(world, 2L);
  578.     put_UWORD(world, istg->maxf);
  579.  
  580.     if (istg->loop) {
  581.         put_name(world, "LOOP", 4);
  582.         put_ULONG(world, 2L);
  583.         put_UWORD(world, istg->loop);
  584.     }
  585.     /* Sort the SOBJ's first? */
  586.  
  587. /* Here is the main loop: */
  588.     for (sobj=istg->head; sobj; sobj=sobj->next) {
  589.         put_name(world, "SOBJ", 4);
  590.         put_ULONG(world, 0L);
  591.  
  592.         pos2 = ftell(world->inp);    /* Save for later */
  593.  
  594.         put_name(world, "NAME", 4);
  595.         put_ULONG(world, 18L);
  596.         put_name(world, sobj->name, 18);
  597.         put_name(world, "STGF", 4);
  598.         put_ULONG(world, 2L);
  599.         put_UWORD(world, sobj->stgf);
  600.         if (sobj->lyr0) process_LYR0(sobj, world);
  601.         if (sobj->glb3) process_GLB3(sobj, world);
  602.         if (sobj->glb2) process_GLB2(sobj, world);
  603.         if (sobj->fil3) process_FIL3(sobj, world);
  604.         if (sobj->file) process_FILE(sobj, world);
  605.         if (sobj->lit2) process_LIT2(sobj, world);
  606.         if (sobj->lite) process_LITE(sobj, world);
  607.         if (sobj->axis) process_AXIS(sobj, world);
  608.         if (sobj->pos2) process_POS2(sobj, world);
  609.         if (sobj->posn) process_POSN(sobj, world);
  610.         if (sobj->aln2) process_ALN2(sobj, world);
  611.         if (sobj->algn) process_ALGN(sobj, world);
  612.         if (sobj->osz2) process_OSZ2(sobj, world);
  613.         if (sobj->osiz) process_OSIZ(sobj, world);
  614.         if (sobj->assc) process_ASSC(sobj, world);
  615.         if (sobj->assc) process_HING(sobj, world);
  616.         if (sobj->spfx) process_SPFX(sobj->spfx, world, 0);
  617.         if (sobj->s2fx) process_SPFX(sobj->s2fx, world, 2);
  618.         if (sobj->s3fx) process_SPFX(sobj->s3fx, world, 3);
  619.         if (sobj->s4fx) process_SPFX(sobj->s4fx, world, 4);
  620.  
  621.         write_size(world, pos2);
  622.     }
  623.  
  624. /* All done. */
  625. }
  626.  
  627. /* Chunks unique to Imagine 2.0 */
  628. static void process_OSIZ(sobj, world)
  629. SOBJ *sobj;
  630. WORLD *world;
  631. {
  632.     register OSIZ *osiz;
  633.  
  634.     for (osiz=sobj->osiz; osiz; osiz=osiz->next) {
  635.         put_name(world, "OSIZ", 4);
  636.         put_ULONG(world, 18L);
  637.         put_UWORD(world, osiz->flags);
  638.         put_UWORD(world, osiz->start);
  639.         put_UWORD(world, osiz->stop);
  640.         put_XYZ(world, &osiz->size);
  641.     }
  642. }
  643.  
  644. static void process_POSN(sobj, world)
  645. SOBJ *sobj;
  646. WORLD *world;
  647. {
  648.     register POSN *posn;
  649.     register PTH2 *pth2;
  650.     int len;
  651.  
  652.     for (posn=sobj->posn; posn; posn=posn->next) {
  653.         if (posn->chunk_type == POSN_CHUNK) {
  654.             put_name(world, "POSN", 4);
  655.             put_ULONG(world, 18L);
  656.             put_UWORD(world, posn->flags);
  657.             put_UWORD(world, posn->start);
  658.             put_UWORD(world, posn->stop);
  659.             put_XYZ(world, &posn->posn);
  660.         }
  661.         else if (posn->chunk_type == PTH2_CHUNK) {
  662.             pth2 = posn;
  663.             len = strlen(pth2->path);
  664.             put_name(world, "PTH2", 4);
  665.             put_ULONG(world, (ULONG)23L+(long)len+(long)((len&1) ? 0 : 1));
  666.             put_UWORD(world, pth2->flags);
  667.             put_UWORD(world, pth2->start);
  668.             put_UWORD(world, pth2->stop);
  669.             put_ULONG(world, pth2->acceleration_frames);
  670.             put_FRACT(world, pth2->start_speed);
  671.             put_ULONG(world, pth2->deacceleration_frames);
  672.             put_FRACT(world, pth2->end_speed);
  673.             /* BCPL string... byte (length) followed by string, then zero */
  674.             /* N.B. trailing zero is not present in original staging file */
  675.             /* except to pad chunk out to a word boundary. [Rob Hounsell] */
  676.             put_UBYTE(world, (UBYTE)len);
  677.             put_name(world, pth2->path, len);
  678.             /* need pad byte only if size of the string is even, since one  */
  679.             /* byte is used up by the length value.                         */
  680.             if (!(len&1)) put_UBYTE(world, 0);        /* pad byte */
  681.          }
  682.         else {
  683.           fprintf(stderr, "Unknown chunk type %d in POSN chain.\n");
  684.         }
  685.     }
  686. }
  687.  
  688. static void process_ALGN(sobj, world)
  689. SOBJ *sobj;
  690. WORLD *world;
  691. {
  692.     register ALGN *algn;
  693.     register PALN *paln;
  694.     register TALN *taln;
  695.     int len;
  696.  
  697.     for (algn=sobj->algn; algn; algn=algn->next) {
  698.         if (algn->chunk_type == ALGN_CHUNK) {
  699.             put_name(world, "ALGN", 4);
  700.             put_ULONG(world, 18L);
  701.             put_UWORD(world, algn->flags);
  702.             put_UWORD(world, algn->start);
  703.             put_UWORD(world, algn->stop);
  704.             put_XYZ(world, &algn->algn);
  705.         }
  706.         else if (algn->chunk_type == PALN_CHUNK) {
  707.             paln = algn;
  708.             put_name(world, "PALN", 4);
  709.             put_ULONG(world, 6L);
  710.             put_UWORD(world, paln->flags);
  711.             put_UWORD(world, paln->start);
  712.             put_UWORD(world, paln->stop);
  713.         }
  714.         else if (algn->chunk_type == TALN_CHUNK) {
  715.             taln = algn;
  716.             len = strlen(taln->trackobj);
  717.             put_name(world, "TALN", 4);
  718.             put_ULONG(world, (ULONG)15L+(long)len+(long)((len&1)? 0 : 1));
  719.             put_UWORD(world, taln->flags);
  720.             put_UWORD(world, taln->start);
  721.             put_UWORD(world, taln->stop);
  722.             put_FRACT(world, taln->initial_y);
  723.             put_FRACT(world, taln->final_y);
  724.             /* BCPL string... byte (length) followed by string, then zero */
  725.  
  726.             /* N.B. trailing zero is not present in original staging file */
  727.             /* except to pad chunk out to a word boundary. [Rob Hounsell] */
  728.             put_UBYTE(world, (UBYTE)len);
  729.             put_name(world, taln->trackobj, len);
  730.             /* need pad byte only if size of the string is even, since one  */
  731.             /* byte is used up by the length value.                         */
  732.             if (!(len&1)) put_UBYTE(world, 0);        /* pad byte */
  733.         }
  734.     }
  735. }
  736.  
  737. static void process_HING(sobj, world)
  738. SOBJ *sobj;
  739. WORLD *world;
  740. {
  741.     register HING *hing;
  742.     int len;
  743.  
  744.     for (hing=sobj->hing; hing; hing=hing->next) {
  745.         len = strlen(hing->hingeobj);
  746.         put_name(world, "HING", 4);
  747.         put_ULONG(world, (ULONG)7L+(long)len+(long)((len&1)? 0 : 1));
  748.         put_UWORD(world, hing->flags);
  749.         put_UWORD(world, hing->start);
  750.         put_UWORD(world, hing->stop);
  751.         /* BCPL string... byte (length) followed by string, then zero */
  752.         /* Not really. See process_ALGN or process_POSN! [Rob Hounsell] */
  753.         put_UBYTE(world, (UBYTE)len);
  754.         put_name(world, hing->hingeobj, len);
  755.         if (!(len&1)) put_UBYTE(world, 0);        /* pad byte */
  756.     }
  757. }
  758.  
  759. static void process_GLB2(sobj, world)
  760. SOBJ *sobj;
  761. WORLD *world;
  762. {
  763.     register GLB2 *glb2;
  764.     int len;
  765.  
  766.     for (glb2=sobj->glb2; glb2; glb2=glb2->next) {
  767.         len = strlen(glb2->globalbrush);
  768.         put_name(world, "GLB2", 4);
  769.         put_ULONG(world, (ULONG)355L+(long)len+(long)((len&1)? 0 : 1));
  770.         put_UWORD(world, glb2->flags);
  771.         put_UWORD(world, glb2->start);
  772.         put_UWORD(world, glb2->stop);
  773.         put_ULONG(world, glb2->sky_blending);
  774.         put_FRACT(world, glb2->starfield);
  775.         put_ULONG(world, glb2->transition);
  776.         /* These colors are stored as FRACTs */
  777.         put_XYZ(world, &glb2->ambient);
  778.         put_XYZ(world, &glb2->horizon);
  779.         put_XYZ(world, &glb2->zenith1);
  780.         put_XYZ(world, &glb2->zenith2);
  781.         put_XYZ(world, &glb2->fog_color);
  782.         put_FRACT(world, glb2->fog_bottom);
  783.         put_FRACT(world, glb2->fog_top);
  784.         put_FRACT(world, glb2->fog_length);
  785.         put_ULONG(world, glb2->brush_seq);
  786.         put_ULONG(world, glb2->backdrop_seq);
  787.         put_name(world, glb2->backdrop, 256);        /* Fixed size */
  788.         /* BCPL string... byte (length) followed by string, then zero if even */
  789.         put_UBYTE(world, (UBYTE)len);
  790.         put_name(world, glb2->globalbrush, len);    /* Var. size */
  791.         if (!(len&1)) put_UBYTE(world, 0);        /* pad byte */
  792.     }
  793. }
  794.  
  795. static void process_LITE(sobj, world)
  796. SOBJ *sobj;
  797. WORLD *world;
  798. {
  799.     register LITE *lite;
  800.  
  801.     for (lite=sobj->lite; lite; lite=lite->next) {
  802.         put_name(world, "LITE", 4);
  803.         put_ULONG(world, 22L);
  804.         put_UWORD(world, lite->flags);
  805.         put_UWORD(world, lite->start);
  806.         put_UWORD(world, lite->stop);
  807.         /* This color is stored as a FRACT */
  808.         put_XYZ(world, &lite->color);
  809.         put_ULONG(world, lite->transition);
  810.     }
  811. }
  812.  
  813. static void process_FILE(sobj, world)
  814. SOBJ *sobj;
  815. WORLD *world;
  816. {
  817.     register SFILE *file;
  818.     int len;
  819.  
  820.     for (file=sobj->file; file; file=file->next) {
  821.         len = strlen(file->object_description);
  822.         put_name(world, "FILE", 4);
  823.         put_ULONG(world, (ULONG)20L+len-(len&1));
  824.         put_UWORD(world, file->flags);
  825.         put_UWORD(world, file->start);
  826.         put_UWORD(world, file->stop);
  827.         put_FRACT(world, file->cycles_to_perform);
  828.         put_FRACT(world, file->initial_cycle_phase);
  829.         put_ULONG(world, file->transition);
  830.         /* BCPL string... byte (length) followed by string */
  831.         put_UBYTE(world, (UBYTE)len);
  832.         put_name(world, file->object_description, len);
  833.         if (!(len&1)) put_UBYTE(world, 0);        /* pad byte */
  834.     }
  835. }
  836.  
  837. /* Chunks unique to Imagine 3.0 or common to both */
  838. static void process_OSZ2(sobj, world)
  839. SOBJ *sobj;
  840. WORLD *world;
  841. {
  842.     register OSZ2 *osz2;
  843.  
  844.     for (osz2=sobj->osz2; osz2; osz2=osz2->next) {
  845.         put_name(world, "OSZ2", 4);
  846.         put_ULONG(world, 26L);
  847.         put_UWORD(world, osz2->flags);
  848.         put_UWORD(world, osz2->start);
  849.         put_UWORD(world, osz2->stop);
  850.         put_XYZ(world, &osz2->size);
  851.         put_FRACT(world, osz2->vel_0);
  852.         put_FRACT(world, osz2->vel_1);
  853.     }
  854. }
  855.  
  856. static void process_POS2(sobj, world)
  857. SOBJ *sobj;
  858. WORLD *world;
  859. {
  860.     register POS2 *pos2;
  861.     register PTH2 *pth2;
  862.     int len;
  863.  
  864.     for (pos2=sobj->pos2; pos2; pos2=pos2->next) {
  865.         if (pos2->chunk_type == POS2_CHUNK) {
  866.             put_name(world, "POS2", 4);
  867.             put_ULONG(world, 26L);
  868.             put_UWORD(world, pos2->flags);
  869.             put_UWORD(world, pos2->start);
  870.             put_UWORD(world, pos2->stop);
  871.             put_XYZ(world, &pos2->pos2);
  872.             put_FRACT(world, pos2->vel_0);
  873.             put_FRACT(world, pos2->vel_1);
  874.         }
  875.         else if (pos2->chunk_type == PTH2_CHUNK) {
  876.             pth2 = pos2;
  877.             len = strlen(pth2->path);
  878.             put_name(world, "PTH2", 4);
  879.             put_ULONG(world, (ULONG)23L+(long)len+(long)((len&1) ? 0 : 1));
  880.             put_UWORD(world, pth2->flags);
  881.             put_UWORD(world, pth2->start);
  882.             put_UWORD(world, pth2->stop);
  883.             put_ULONG(world, pth2->acceleration_frames);
  884.             put_FRACT(world, pth2->start_speed);
  885.             put_ULONG(world, pth2->deacceleration_frames);
  886.             put_FRACT(world, pth2->end_speed);
  887.             /* BCPL string... byte (length) followed by string, then zero */
  888.             /* N.B. trailing zero is not present in original staging file */
  889.             /* except to pad chunk out to a word boundary. [Rob Hounsell] */
  890.             put_UBYTE(world, (UBYTE)len);
  891.             put_name(world, pth2->path, len);
  892.             /* need pad byte only if size of the string is even, since one  */
  893.             /* byte is used up by the length value.                         */
  894.             if (!(len&1)) put_UBYTE(world, 0);        /* pad byte */
  895.          }
  896.         else {
  897.           fprintf(stderr, "Unknown chunk type %d in POS2 chain.\n");
  898.         }
  899.     }
  900. }
  901.  
  902. static void process_ALN2(sobj, world)
  903. SOBJ *sobj;
  904. WORLD *world;
  905. {
  906.     register ALN2 *aln2;
  907.     register PALN *paln;
  908.     register TALN *taln;
  909.     int len;
  910.  
  911.     for (aln2=sobj->aln2; aln2; aln2=aln2->next) {
  912.         if (aln2->chunk_type == ALN2_CHUNK) {
  913.             put_name(world, "ALN2", 4);
  914.             put_ULONG(world, 26L);
  915.             put_UWORD(world, aln2->flags);
  916.             put_UWORD(world, aln2->start);
  917.             put_UWORD(world, aln2->stop);
  918.             put_XYZ(world, &aln2->aln2);
  919.             put_FRACT(world, aln2->vel_0);
  920.             put_FRACT(world, aln2->vel_1);
  921.         }
  922.         else if (aln2->chunk_type == PALN_CHUNK) {
  923.             paln = aln2;
  924.             put_name(world, "PALN", 4);
  925.             put_ULONG(world, 6L);
  926.             put_UWORD(world, paln->flags);
  927.             put_UWORD(world, paln->start);
  928.             put_UWORD(world, paln->stop);
  929.         }
  930.         else if (aln2->chunk_type == TALN_CHUNK) {
  931.             taln = aln2;
  932.             len = strlen(taln->trackobj);
  933.             put_name(world, "TALN", 4);
  934.             put_ULONG(world, (ULONG)15L+(long)len+(long)((len&1)? 0 : 1));
  935.             put_UWORD(world, taln->flags);
  936.             put_UWORD(world, taln->start);
  937.             put_UWORD(world, taln->stop);
  938.             put_FRACT(world, taln->initial_y);
  939.             put_FRACT(world, taln->final_y);
  940.             /* BCPL string... byte (length) followed by string, then zero */
  941.  
  942.             /* N.B. trailing zero is not present in original staging file */
  943.             /* except to pad chunk out to a word boundary. [Rob Hounsell] */
  944.             put_UBYTE(world, (UBYTE)len);
  945.             put_name(world, taln->trackobj, len);
  946.             /* need pad byte only if size of the string is even, since one  */
  947.             /* byte is used up by the length value.                         */
  948.             if (!(len&1)) put_UBYTE(world, 0);        /* pad byte */
  949.         }
  950.     }
  951. }
  952.  
  953. static void process_ASSC(sobj, world)
  954. SOBJ *sobj;
  955. WORLD *world;
  956. {
  957.     register ASSC *assc;
  958.     int len;
  959.  
  960.     for (assc=sobj->assc; assc; assc=assc->next) {
  961.         len = strlen(assc->assc_obj);
  962.         if (len > 17) {
  963.             fprintf(stderr, "ASSC object \"%s\" is longer than 17 chars. Truncating...\n");
  964.             len = 17;
  965.         }
  966.         put_name(world, "ASSC", 4);
  967.         put_ULONG(world, (ULONG)7L+(long)len+(long)((len&1)? 0 : 1));
  968.         put_UWORD(world, assc->flags);
  969.         put_UWORD(world, assc->start);
  970.         put_UWORD(world, assc->stop);
  971.         /* BCPL string... byte (length) followed by string, then zero if needed */
  972.         put_UBYTE(world, (UBYTE)len);
  973.         put_name(world, assc->assc_obj, len);
  974.         if (!(len&1)) put_UBYTE(world, 0);        /* pad byte */
  975.     }
  976. }
  977.  
  978. static void process_LYR0(sobj, world)
  979. SOBJ *sobj;
  980. WORLD *world;
  981. {
  982.     register LYR0 *lyr0;
  983.  
  984.     for (lyr0=sobj->lyr0; lyr0; lyr0=lyr0->next) {
  985.         put_name(world, "LYR0", 4);
  986.         put_ULONG(world, (ULONG)2L);
  987.         put_UWORD(world, lyr0->layer);
  988.     }
  989. }
  990.  
  991.  
  992. static void process_GLB3(sobj, world) SOBJ *sobj;
  993. WORLD *world;
  994. {
  995.     register GLB3 *glb3;
  996.     int len;
  997.  
  998.     for (glb3=sobj->glb3; glb3; glb3=glb3->next) {
  999.         len = strlen(glb3->globalbrush);
  1000.         put_name(world, "GLB3", 4);
  1001.     /* if len is even, add 1 for the pad byte, since the string starts */
  1002.     /* on an odd byte following the length byte, and is padded to make */
  1003.     /* the next chunk start on an even byte boundary.                  */
  1004.         put_ULONG(world, (ULONG)351L+(long)len+(long)((len&1)? 0 : 1));
  1005.         put_UWORD(world, glb3->flags);
  1006.         put_UWORD(world, glb3->start);
  1007.         put_UWORD(world, glb3->stop);
  1008.         put_ULONG(world, glb3->brush_seq);
  1009.         put_FRACT(world, glb3->starfield);
  1010.         put_ULONG(world, glb3->transition);
  1011.         /* These colors are stored as FRACTs */
  1012.         put_XYZ(world, &glb3->ambient);
  1013.         put_XYZ(world, &glb3->horizon);
  1014.         put_XYZ(world, &glb3->zenith1);
  1015.         put_XYZ(world, &glb3->zenith2);
  1016.         put_XYZ(world, &glb3->fog_color);
  1017.         put_FRACT(world, glb3->fog_bottom);
  1018.         put_FRACT(world, glb3->fog_top);
  1019.         put_FRACT(world, glb3->fog_length);
  1020.         put_ULONG(world, glb3->backdrop_seq);
  1021.         put_name(world, glb3->backdrop, 256);        /* Fixed size */
  1022.         /* BCPL string... byte (length) followed by string */
  1023.         put_UBYTE(world, (UBYTE)len);
  1024.         put_name(world, glb3->globalbrush, len);    /* Var. size */
  1025.         /* put_UBYTE(world, 0); - doesn't seem to be used in 3.0 */
  1026.         if (!(len&1)) put_UBYTE(world, 0); /* pad byte */
  1027.     }
  1028. }
  1029.  
  1030. static void process_AXIS(sobj, world)
  1031. SOBJ *sobj;
  1032. WORLD *world;
  1033. {
  1034.     register SAXIS *axis;
  1035.  
  1036.     for (axis=sobj->axis; axis; axis=axis->next) {
  1037.         put_name(world, "AXIS", 4);
  1038.         put_ULONG(world, 6L);
  1039.         put_UWORD(world, axis->flags);
  1040.         put_UWORD(world, axis->start);
  1041.         put_UWORD(world, axis->stop);
  1042.     }
  1043. }
  1044.  
  1045. static void process_LIT2(sobj, world)
  1046. SOBJ *sobj;
  1047. WORLD *world;
  1048. {
  1049.     register LIT2 *lit2;
  1050.  
  1051.     for (lit2=sobj->lit2; lit2; lit2=lit2->next) {
  1052.         put_name(world, "LIT2", 4);
  1053.         put_ULONG(world, 22L);
  1054.         put_UWORD(world, lit2->flags);
  1055.         put_UWORD(world, lit2->start);
  1056.         put_UWORD(world, lit2->stop);
  1057.         /* This color is stored as a FRACT */
  1058.         put_XYZ(world, &lit2->color);
  1059.         put_ULONG(world, lit2->transition);
  1060.     }
  1061. }
  1062.  
  1063. static void process_FIL3(sobj, world)
  1064. SOBJ *sobj;
  1065. WORLD *world;
  1066. {
  1067.     register FIL3 *fil3;
  1068.     int len;
  1069.  
  1070.     for (fil3=sobj->fil3; fil3; fil3=fil3->next) {
  1071.         len = strlen(fil3->object_description);
  1072.         put_name(world, "FIL3", 4);
  1073.         /* if len is even, add 1 for the pad byte, since the string starts */
  1074.         /* on an odd byte following the length byte, and is padded to make */
  1075.         /* the next chunk start on an even byte boundary.                  */
  1076.         put_ULONG(world, (ULONG)41L+(long)len+(long)((len&1)? 0 : 1));
  1077.         put_UWORD(world, fil3->flags);
  1078.         put_UWORD(world, fil3->start);
  1079.         put_UWORD(world, fil3->stop);
  1080.         put_FRACT(world, fil3->cycles_to_perform);
  1081.         put_FRACT(world, fil3->initial_cycle_phase);
  1082.         put_FRACT(world, fil3->vel_0);
  1083.         put_FRACT(world, fil3->vel_1);
  1084.         if (strlen(fil3->state) > 17) {
  1085.             fprintf(stderr, "STATE string \"%s\" is longer than 17 chars. Truncating...\n");
  1086.         }
  1087.         put_name(world, fil3->state, 18);        /* Fixed size */
  1088.         /* BCPL string... byte (length) followed by string */
  1089.         put_UBYTE(world, (UBYTE)len);
  1090.         put_name(world, fil3->object_description, len);
  1091.         if (!(len&1)) put_UBYTE(world, 0);    /* pad byte, since string starts */
  1092.                                         /* on an odd byte                */
  1093.     }
  1094. }
  1095.  
  1096. static void process_SPFX(spfx_ptr, world, index)
  1097. SPFX *spfx_ptr;
  1098. WORLD *world;
  1099. int index;
  1100. {
  1101.     register SPFX *spfx;
  1102.     long pos, cur;  /* file pointer position info */
  1103.     int len, data_len;
  1104.  
  1105.     for (spfx=spfx_ptr; spfx; spfx=spfx->next) {
  1106.         len = strlen(spfx->effect);
  1107.         switch (index) {
  1108.             case 0:
  1109.                 put_name(world, "SPFX", 4);
  1110.                 break;
  1111.             case 2:
  1112.                 put_name(world, "S2FX", 4);
  1113.                 break;
  1114.             case 3:
  1115.                 put_name(world, "S3FX", 4);
  1116.                 break;
  1117.             case 4:
  1118.                 put_name(world, "S4FX", 4);
  1119.         }
  1120.  
  1121.         /* if len is even, add 1 for the pad byte, since the string starts */
  1122.         /* on an odd byte following the length byte, and is padded to make */
  1123.         /* the next chunk start on an even byte boundary.                  */
  1124.         put_ULONG(world, 0L);        /* Fill this in later [seek(,4L,0)] */
  1125.         pos = ftell(world->inp);    /* Save where this length word is */
  1126.         put_UWORD(world, spfx->flags);
  1127.         put_UWORD(world, spfx->start);
  1128.         put_UWORD(world, spfx->stop);
  1129.         /* BCPL string... byte (length) followed by string */
  1130.         put_UBYTE(world, (UBYTE)len);
  1131.         put_name(world, spfx->effect, len);
  1132.         if (!(len&1)) put_UBYTE(world, 0);  /* pad byte, since string starts */
  1133.                                             /* on an odd byte                */
  1134.         data_len = decode_data(world->inp, spfx->effect_data);
  1135.  
  1136.         if (data_len < 0) 
  1137.             fprintf(stderr, "ERROR: decode_data return %d\n!", data_len);
  1138.  
  1139.     /* now add up all the lengths and insert it after the SPFX token */
  1140.         cur = ftell(world->inp);
  1141.         fseek(world->inp, pos-4L, 0);
  1142.         put_ULONG(world, (ULONG)7L+(long)data_len+(long)len+(long)((len&1)? 0 : 1));
  1143.         fseek(world->inp, cur, 0);
  1144.     }
  1145. }
  1146.