tennis.map: Texture tweak
[neverball] / share / solid_base.c
1 /*
2  * Copyright (C) 2003 Robert Kooima
3  *
4  * NEVERBALL is  free software; you can redistribute  it and/or modify
5  * it under the  terms of the GNU General  Public License as published
6  * by the Free  Software Foundation; either version 2  of the License,
7  * or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT  ANY  WARRANTY;  without   even  the  implied  warranty  of
11  * MERCHANTABILITY or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU
12  * General Public License for more details.
13  */
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18
19 #include "solid_base.h"
20 #include "base_config.h"
21 #include "binary.h"
22 #include "common.h"
23 #include "fs.h"
24 #include "vec3.h"
25
26 enum
27 {
28     SOL_VER_MINIMUM = 6,
29     SOL_VER_GLES,
30     SOL_VER_CURRENT = SOL_VER_GLES
31 };
32
33 #define SOL_MAGIC (0xAF | 'S' << 8 | 'O' << 16 | 'L' << 24)
34
35 /*---------------------------------------------------------------------------*/
36
37 static int sol_version;
38
39 static int sol_file(fs_file fin)
40 {
41     int magic;
42     int version;
43
44     get_index(fin, &magic);
45     get_index(fin, &version);
46
47     if (magic != SOL_MAGIC || (version < SOL_VER_MINIMUM ||
48                                version > SOL_VER_CURRENT))
49         return 0;
50
51     sol_version = version;
52
53     return 1;
54 }
55
56 static void sol_load_mtrl(fs_file fin, struct b_mtrl *mp)
57 {
58     get_array(fin,  mp->d, 4);
59     get_array(fin,  mp->a, 4);
60     get_array(fin,  mp->s, 4);
61     get_array(fin,  mp->e, 4);
62     get_array(fin,  mp->h, 1);
63     get_index(fin, &mp->fl);
64
65     fs_read(mp->f, 1, PATHMAX, fin);
66
67     if (sol_version < SOL_VER_GLES)
68     {
69         static const int flags[][2] = {
70             { 1, M_SHADOWED },
71             { 2, M_TRANSPARENT },
72             { 4, M_REFLECTIVE | M_SHADOWED },
73             { 8, M_ENVIRONMENT },
74             { 16, M_ADDITIVE },
75             { 32, M_CLAMP_S | M_CLAMP_T },
76             { 64, M_DECAL },
77             { 128, M_TWO_SIDED }
78         };
79
80         /* Convert 1.5.4 material flags. */
81
82         if (mp->fl)
83         {
84             int i, f;
85
86             for (f = 0, i = 0; i < ARRAYSIZE(flags); i++)
87                 if (mp->fl & flags[i][0])
88                     f |= flags[i][1];
89
90             mp->fl = f;
91         }
92         else
93         {
94             /* Must be "mtrl/invisible". */
95
96             mp->fl = M_TRANSPARENT;
97             mp->d[3] = 0.0f;
98         }
99     }
100 }
101
102 static void sol_load_vert(fs_file fin, struct b_vert *vp)
103 {
104     get_array(fin,  vp->p, 3);
105 }
106
107 static void sol_load_edge(fs_file fin, struct b_edge *ep)
108 {
109     get_index(fin, &ep->vi);
110     get_index(fin, &ep->vj);
111 }
112
113 static void sol_load_side(fs_file fin, struct b_side *sp)
114 {
115     get_array(fin,  sp->n, 3);
116     get_float(fin, &sp->d);
117 }
118
119 static void sol_load_texc(fs_file fin, struct b_texc *tp)
120 {
121     get_array(fin,  tp->u, 2);
122 }
123
124 static void sol_load_offs(fs_file fin, struct b_offs *op)
125 {
126     get_index(fin, &op->ti);
127     get_index(fin, &op->si);
128     get_index(fin, &op->vi);
129 }
130
131 static void sol_load_geom(fs_file fin, struct b_geom *gp, struct s_base *fp)
132 {
133     get_index(fin, &gp->mi);
134
135     if (sol_version >= SOL_VER_GLES)
136     {
137         get_index(fin, &gp->oi);
138         get_index(fin, &gp->oj);
139         get_index(fin, &gp->ok);
140     }
141     else
142     {
143         struct b_offs ov[3];
144         int i, j, iv[3], oc;
145         void *p;
146
147         oc = 0;
148
149         for (i = 0; i < 3; i++)
150         {
151             get_index(fin, &ov[i].ti);
152             get_index(fin, &ov[i].si);
153             get_index(fin, &ov[i].vi);
154
155             iv[i] = -1;
156
157             for (j = 0; j < fp->oc; j++)
158                 if (ov[i].ti == fp->ov[j].ti &&
159                     ov[i].si == fp->ov[j].si &&
160                     ov[i].vi == fp->ov[j].vi)
161                 {
162                     iv[i] = j;
163                     break;
164                 }
165
166             if (j == fp->oc)
167                 oc++;
168         }
169
170         if (oc && (p = realloc(fp->ov, sizeof (struct b_offs) * (fp->oc + oc))))
171         {
172             fp->ov = p;
173
174             for (i = 0; i < 3; i++)
175                 if (iv[i] < 0)
176                 {
177                     fp->ov[fp->oc] = ov[i];
178                     iv[i] = fp->oc++;
179                 }
180         }
181
182         gp->oi = iv[0];
183         gp->oj = iv[1];
184         gp->ok = iv[2];
185     }
186 }
187
188 static void sol_load_lump(fs_file fin, struct b_lump *lp)
189 {
190     get_index(fin, &lp->fl);
191     get_index(fin, &lp->v0);
192     get_index(fin, &lp->vc);
193     get_index(fin, &lp->e0);
194     get_index(fin, &lp->ec);
195     get_index(fin, &lp->g0);
196     get_index(fin, &lp->gc);
197     get_index(fin, &lp->s0);
198     get_index(fin, &lp->sc);
199 }
200
201 static void sol_load_node(fs_file fin, struct b_node *np)
202 {
203     get_index(fin, &np->si);
204     get_index(fin, &np->ni);
205     get_index(fin, &np->nj);
206     get_index(fin, &np->l0);
207     get_index(fin, &np->lc);
208 }
209
210 static void sol_load_path(fs_file fin, struct b_path *pp)
211 {
212     get_array(fin,  pp->p, 3);
213     get_float(fin, &pp->t);
214     get_index(fin, &pp->pi);
215     get_index(fin, &pp->f);
216     get_index(fin, &pp->s);
217
218     pp->tm = TIME_TO_MS(pp->t);
219     pp->t  = MS_TO_TIME(pp->tm);
220
221     if (sol_version >= SOL_VER_GLES)
222         get_index(fin, &pp->fl);
223
224     pp->e[0] = 1.0f;
225     pp->e[1] = 0.0f;
226     pp->e[2] = 0.0f;
227     pp->e[3] = 0.0f;
228
229     if (pp->fl & P_ORIENTED)
230         get_array(fin, pp->e, 4);
231 }
232
233 static void sol_load_body(fs_file fin, struct b_body *bp)
234 {
235     get_index(fin, &bp->pi);
236     get_index(fin, &bp->ni);
237     get_index(fin, &bp->l0);
238     get_index(fin, &bp->lc);
239     get_index(fin, &bp->g0);
240     get_index(fin, &bp->gc);
241 }
242
243 static void sol_load_item(fs_file fin, struct b_item *hp)
244 {
245     get_array(fin,  hp->p, 3);
246     get_index(fin, &hp->t);
247     get_index(fin, &hp->n);
248 }
249
250 static void sol_load_goal(fs_file fin, struct b_goal *zp)
251 {
252     get_array(fin,  zp->p, 3);
253     get_float(fin, &zp->r);
254 }
255
256 static void sol_load_swch(fs_file fin, struct b_swch *xp)
257 {
258     float f;
259     int i;
260
261     get_array(fin,  xp->p, 3);
262     get_float(fin, &xp->r);
263     get_index(fin, &xp->pi);
264     get_float(fin, &xp->t);
265     get_float(fin, &f);
266     get_index(fin, &xp->f);
267     get_index(fin, &i);
268     get_index(fin, &xp->i);
269
270     xp->tm = TIME_TO_MS(xp->t);
271     xp->t = MS_TO_TIME(xp->tm);
272 }
273
274 static void sol_load_bill(fs_file fin, struct b_bill *rp)
275 {
276     get_index(fin, &rp->fl);
277     get_index(fin, &rp->mi);
278     get_float(fin, &rp->t);
279     get_float(fin, &rp->d);
280     get_array(fin,  rp->w,  3);
281     get_array(fin,  rp->h,  3);
282     get_array(fin,  rp->rx, 3);
283     get_array(fin,  rp->ry, 3);
284     get_array(fin,  rp->rz, 3);
285     get_array(fin,  rp->p,  3);
286 }
287
288 static void sol_load_jump(fs_file fin, struct b_jump *jp)
289 {
290     get_array(fin,  jp->p, 3);
291     get_array(fin,  jp->q, 3);
292     get_float(fin, &jp->r);
293 }
294
295 static void sol_load_ball(fs_file fin, struct b_ball *up)
296 {
297     get_array(fin,  up->p, 3);
298     get_float(fin, &up->r);
299 }
300
301 static void sol_load_view(fs_file fin, struct b_view *wp)
302 {
303     get_array(fin,  wp->p, 3);
304     get_array(fin,  wp->q, 3);
305 }
306
307 static void sol_load_dict(fs_file fin, struct b_dict *dp)
308 {
309     get_index(fin, &dp->ai);
310     get_index(fin, &dp->aj);
311 }
312
313 static void sol_load_indx(fs_file fin, struct s_base *fp)
314 {
315     get_index(fin, &fp->ac);
316     get_index(fin, &fp->dc);
317     get_index(fin, &fp->mc);
318     get_index(fin, &fp->vc);
319     get_index(fin, &fp->ec);
320     get_index(fin, &fp->sc);
321     get_index(fin, &fp->tc);
322
323     if (sol_version >= SOL_VER_GLES)
324         get_index(fin, &fp->oc);
325
326     get_index(fin, &fp->gc);
327     get_index(fin, &fp->lc);
328     get_index(fin, &fp->nc);
329     get_index(fin, &fp->pc);
330     get_index(fin, &fp->bc);
331     get_index(fin, &fp->hc);
332     get_index(fin, &fp->zc);
333     get_index(fin, &fp->jc);
334     get_index(fin, &fp->xc);
335     get_index(fin, &fp->rc);
336     get_index(fin, &fp->uc);
337     get_index(fin, &fp->wc);
338     get_index(fin, &fp->ic);
339 }
340
341 static int sol_load_file(fs_file fin, struct s_base *fp)
342 {
343     int i;
344
345     if (!sol_file(fin))
346         return 0;
347
348     sol_load_indx(fin, fp);
349
350     if (fp->ac)
351         fp->av = (char *)          calloc(fp->ac, sizeof (*fp->av));
352     if (fp->mc)
353         fp->mv = (struct b_mtrl *) calloc(fp->mc, sizeof (*fp->mv));
354     if (fp->vc)
355         fp->vv = (struct b_vert *) calloc(fp->vc, sizeof (*fp->vv));
356     if (fp->ec)
357         fp->ev = (struct b_edge *) calloc(fp->ec, sizeof (*fp->ev));
358     if (fp->sc)
359         fp->sv = (struct b_side *) calloc(fp->sc, sizeof (*fp->sv));
360     if (fp->tc)
361         fp->tv = (struct b_texc *) calloc(fp->tc, sizeof (*fp->tv));
362     if (fp->oc)
363         fp->ov = (struct b_offs *) calloc(fp->oc, sizeof (*fp->ov));
364     if (fp->gc)
365         fp->gv = (struct b_geom *) calloc(fp->gc, sizeof (*fp->gv));
366     if (fp->lc)
367         fp->lv = (struct b_lump *) calloc(fp->lc, sizeof (*fp->lv));
368     if (fp->nc)
369         fp->nv = (struct b_node *) calloc(fp->nc, sizeof (*fp->nv));
370     if (fp->pc)
371         fp->pv = (struct b_path *) calloc(fp->pc, sizeof (*fp->pv));
372     if (fp->bc)
373         fp->bv = (struct b_body *) calloc(fp->bc, sizeof (*fp->bv));
374     if (fp->hc)
375         fp->hv = (struct b_item *) calloc(fp->hc, sizeof (*fp->hv));
376     if (fp->zc)
377         fp->zv = (struct b_goal *) calloc(fp->zc, sizeof (*fp->zv));
378     if (fp->jc)
379         fp->jv = (struct b_jump *) calloc(fp->jc, sizeof (*fp->jv));
380     if (fp->xc)
381         fp->xv = (struct b_swch *) calloc(fp->xc, sizeof (*fp->xv));
382     if (fp->rc)
383         fp->rv = (struct b_bill *) calloc(fp->rc, sizeof (*fp->rv));
384     if (fp->uc)
385         fp->uv = (struct b_ball *) calloc(fp->uc, sizeof (*fp->uv));
386     if (fp->wc)
387         fp->wv = (struct b_view *) calloc(fp->wc, sizeof (*fp->wv));
388     if (fp->dc)
389         fp->dv = (struct b_dict *) calloc(fp->dc, sizeof (*fp->dv));
390     if (fp->ic)
391         fp->iv = (int *)           calloc(fp->ic, sizeof (*fp->iv));
392
393     if (fp->ac)
394         fs_read(fp->av, 1, fp->ac, fin);
395
396     for (i = 0; i < fp->dc; i++) sol_load_dict(fin, fp->dv + i);
397     for (i = 0; i < fp->mc; i++) sol_load_mtrl(fin, fp->mv + i);
398     for (i = 0; i < fp->vc; i++) sol_load_vert(fin, fp->vv + i);
399     for (i = 0; i < fp->ec; i++) sol_load_edge(fin, fp->ev + i);
400     for (i = 0; i < fp->sc; i++) sol_load_side(fin, fp->sv + i);
401     for (i = 0; i < fp->tc; i++) sol_load_texc(fin, fp->tv + i);
402     for (i = 0; i < fp->oc; i++) sol_load_offs(fin, fp->ov + i);
403     for (i = 0; i < fp->gc; i++) sol_load_geom(fin, fp->gv + i, fp);
404     for (i = 0; i < fp->lc; i++) sol_load_lump(fin, fp->lv + i);
405     for (i = 0; i < fp->nc; i++) sol_load_node(fin, fp->nv + i);
406     for (i = 0; i < fp->pc; i++) sol_load_path(fin, fp->pv + i);
407     for (i = 0; i < fp->bc; i++) sol_load_body(fin, fp->bv + i);
408     for (i = 0; i < fp->hc; i++) sol_load_item(fin, fp->hv + i);
409     for (i = 0; i < fp->zc; i++) sol_load_goal(fin, fp->zv + i);
410     for (i = 0; i < fp->jc; i++) sol_load_jump(fin, fp->jv + i);
411     for (i = 0; i < fp->xc; i++) sol_load_swch(fin, fp->xv + i);
412     for (i = 0; i < fp->rc; i++) sol_load_bill(fin, fp->rv + i);
413     for (i = 0; i < fp->uc; i++) sol_load_ball(fin, fp->uv + i);
414     for (i = 0; i < fp->wc; i++) sol_load_view(fin, fp->wv + i);
415     for (i = 0; i < fp->ic; i++) get_index(fin, fp->iv + i);
416
417     /* Magically "fix" all of our code. */
418
419     if (!fp->uc)
420     {
421         fp->uc = 1;
422         fp->uv = (struct b_ball *) calloc(fp->uc, sizeof (*fp->uv));
423     }
424
425     return 1;
426 }
427
428 static int sol_load_head(fs_file fin, struct s_base *fp)
429 {
430     if (!sol_file(fin))
431         return 0;
432
433     sol_load_indx(fin, fp);
434
435     if (fp->ac)
436     {
437         fp->av = (char *) calloc(fp->ac, sizeof (*fp->av));
438         fs_read(fp->av, 1, fp->ac, fin);
439     }
440
441     if (fp->dc)
442     {
443         int i;
444
445         fp->dv = (struct b_dict *) calloc(fp->dc, sizeof (*fp->dv));
446
447         for (i = 0; i < fp->dc; i++)
448             sol_load_dict(fin, fp->dv + i);
449     }
450
451     return 1;
452 }
453
454 int sol_load_base(struct s_base *fp, const char *filename)
455 {
456     fs_file fin;
457     int res = 0;
458
459     memset(fp, 0, sizeof (*fp));
460
461     if ((fin = fs_open(filename, "r")))
462     {
463         res = sol_load_file(fin, fp);
464         fs_close(fin);
465     }
466     return res;
467 }
468
469 int sol_load_meta(struct s_base *fp, const char *filename)
470 {
471     fs_file fin;
472     int res = 0;
473
474     if ((fin = fs_open(filename, "r")))
475     {
476         res = sol_load_head(fin, fp);
477         fs_close(fin);
478     }
479     return res;
480 }
481
482 void sol_free_base(struct s_base *fp)
483 {
484     if (fp->av) free(fp->av);
485     if (fp->mv) free(fp->mv);
486     if (fp->vv) free(fp->vv);
487     if (fp->ev) free(fp->ev);
488     if (fp->sv) free(fp->sv);
489     if (fp->tv) free(fp->tv);
490     if (fp->ov) free(fp->ov);
491     if (fp->gv) free(fp->gv);
492     if (fp->lv) free(fp->lv);
493     if (fp->nv) free(fp->nv);
494     if (fp->pv) free(fp->pv);
495     if (fp->bv) free(fp->bv);
496     if (fp->hv) free(fp->hv);
497     if (fp->zv) free(fp->zv);
498     if (fp->jv) free(fp->jv);
499     if (fp->xv) free(fp->xv);
500     if (fp->rv) free(fp->rv);
501     if (fp->uv) free(fp->uv);
502     if (fp->wv) free(fp->wv);
503     if (fp->dv) free(fp->dv);
504     if (fp->iv) free(fp->iv);
505
506     memset(fp, 0, sizeof (*fp));
507 }
508
509 /*---------------------------------------------------------------------------*/
510
511 static void sol_stor_mtrl(fs_file fout, struct b_mtrl *mp)
512 {
513     put_array(fout, mp->d, 4);
514     put_array(fout, mp->a, 4);
515     put_array(fout, mp->s, 4);
516     put_array(fout, mp->e, 4);
517     put_array(fout, mp->h, 1);
518     put_index(fout, mp->fl);
519
520     fs_write(mp->f, 1, PATHMAX, fout);
521 }
522
523 static void sol_stor_vert(fs_file fout, struct b_vert *vp)
524 {
525     put_array(fout,  vp->p, 3);
526 }
527
528 static void sol_stor_edge(fs_file fout, struct b_edge *ep)
529 {
530     put_index(fout, ep->vi);
531     put_index(fout, ep->vj);
532 }
533
534 static void sol_stor_side(fs_file fout, struct b_side *sp)
535 {
536     put_array(fout, sp->n, 3);
537     put_float(fout, sp->d);
538 }
539
540 static void sol_stor_texc(fs_file fout, struct b_texc *tp)
541 {
542     put_array(fout,  tp->u, 2);
543 }
544
545 static void sol_stor_offs(fs_file fout, struct b_offs *op)
546 {
547     put_index(fout, op->ti);
548     put_index(fout, op->si);
549     put_index(fout, op->vi);
550 }
551
552 static void sol_stor_geom(fs_file fout, struct b_geom *gp)
553 {
554     put_index(fout, gp->mi);
555     put_index(fout, gp->oi);
556     put_index(fout, gp->oj);
557     put_index(fout, gp->ok);
558 }
559
560 static void sol_stor_lump(fs_file fout, struct b_lump *lp)
561 {
562     put_index(fout, lp->fl);
563     put_index(fout, lp->v0);
564     put_index(fout, lp->vc);
565     put_index(fout, lp->e0);
566     put_index(fout, lp->ec);
567     put_index(fout, lp->g0);
568     put_index(fout, lp->gc);
569     put_index(fout, lp->s0);
570     put_index(fout, lp->sc);
571 }
572
573 static void sol_stor_node(fs_file fout, struct b_node *np)
574 {
575     put_index(fout, np->si);
576     put_index(fout, np->ni);
577     put_index(fout, np->nj);
578     put_index(fout, np->l0);
579     put_index(fout, np->lc);
580 }
581
582 static void sol_stor_path(fs_file fout, struct b_path *pp)
583 {
584     put_array(fout, pp->p, 3);
585     put_float(fout, pp->t);
586     put_index(fout, pp->pi);
587     put_index(fout, pp->f);
588     put_index(fout, pp->s);
589     put_index(fout, pp->fl);
590
591     if (pp->fl & P_ORIENTED)
592         put_array(fout, pp->e, 4);
593 }
594
595 static void sol_stor_body(fs_file fout, struct b_body *bp)
596 {
597     put_index(fout, bp->pi);
598     put_index(fout, bp->ni);
599     put_index(fout, bp->l0);
600     put_index(fout, bp->lc);
601     put_index(fout, bp->g0);
602     put_index(fout, bp->gc);
603 }
604
605 static void sol_stor_item(fs_file fout, struct b_item *hp)
606 {
607     put_array(fout, hp->p, 3);
608     put_index(fout, hp->t);
609     put_index(fout, hp->n);
610 }
611
612 static void sol_stor_goal(fs_file fout, struct b_goal *zp)
613 {
614     put_array(fout, zp->p, 3);
615     put_float(fout, zp->r);
616 }
617
618 static void sol_stor_swch(fs_file fout, struct b_swch *xp)
619 {
620     put_array(fout, xp->p, 3);
621     put_float(fout, xp->r);
622     put_index(fout, xp->pi);
623     put_float(fout, xp->t);
624     put_float(fout, xp->t);
625     put_index(fout, xp->f);
626     put_index(fout, xp->f);
627     put_index(fout, xp->i);
628 }
629
630 static void sol_stor_bill(fs_file fout, struct b_bill *rp)
631 {
632     put_index(fout, rp->fl);
633     put_index(fout, rp->mi);
634     put_float(fout, rp->t);
635     put_float(fout, rp->d);
636     put_array(fout, rp->w,  3);
637     put_array(fout, rp->h,  3);
638     put_array(fout, rp->rx, 3);
639     put_array(fout, rp->ry, 3);
640     put_array(fout, rp->rz, 3);
641     put_array(fout, rp->p,  3);
642 }
643
644 static void sol_stor_jump(fs_file fout, struct b_jump *jp)
645 {
646     put_array(fout, jp->p, 3);
647     put_array(fout, jp->q, 3);
648     put_float(fout, jp->r);
649 }
650
651 static void sol_stor_ball(fs_file fout, struct b_ball *bp)
652 {
653     put_array(fout, bp->p, 3);
654     put_float(fout, bp->r);
655 }
656
657 static void sol_stor_view(fs_file fout, struct b_view *wp)
658 {
659     put_array(fout,  wp->p, 3);
660     put_array(fout,  wp->q, 3);
661 }
662
663 static void sol_stor_dict(fs_file fout, struct b_dict *dp)
664 {
665     put_index(fout, dp->ai);
666     put_index(fout, dp->aj);
667 }
668
669 static void sol_stor_file(fs_file fout, struct s_base *fp)
670 {
671     int i;
672     int magic   = SOL_MAGIC;
673     int version = SOL_VER_CURRENT;
674
675     put_index(fout, magic);
676     put_index(fout, version);
677
678     put_index(fout, fp->ac);
679     put_index(fout, fp->dc);
680     put_index(fout, fp->mc);
681     put_index(fout, fp->vc);
682     put_index(fout, fp->ec);
683     put_index(fout, fp->sc);
684     put_index(fout, fp->tc);
685     put_index(fout, fp->oc);
686     put_index(fout, fp->gc);
687     put_index(fout, fp->lc);
688     put_index(fout, fp->nc);
689     put_index(fout, fp->pc);
690     put_index(fout, fp->bc);
691     put_index(fout, fp->hc);
692     put_index(fout, fp->zc);
693     put_index(fout, fp->jc);
694     put_index(fout, fp->xc);
695     put_index(fout, fp->rc);
696     put_index(fout, fp->uc);
697     put_index(fout, fp->wc);
698     put_index(fout, fp->ic);
699
700     fs_write(fp->av, 1, fp->ac, fout);
701
702     for (i = 0; i < fp->dc; i++) sol_stor_dict(fout, fp->dv + i);
703     for (i = 0; i < fp->mc; i++) sol_stor_mtrl(fout, fp->mv + i);
704     for (i = 0; i < fp->vc; i++) sol_stor_vert(fout, fp->vv + i);
705     for (i = 0; i < fp->ec; i++) sol_stor_edge(fout, fp->ev + i);
706     for (i = 0; i < fp->sc; i++) sol_stor_side(fout, fp->sv + i);
707     for (i = 0; i < fp->tc; i++) sol_stor_texc(fout, fp->tv + i);
708     for (i = 0; i < fp->oc; i++) sol_stor_offs(fout, fp->ov + i);
709     for (i = 0; i < fp->gc; i++) sol_stor_geom(fout, fp->gv + i);
710     for (i = 0; i < fp->lc; i++) sol_stor_lump(fout, fp->lv + i);
711     for (i = 0; i < fp->nc; i++) sol_stor_node(fout, fp->nv + i);
712     for (i = 0; i < fp->pc; i++) sol_stor_path(fout, fp->pv + i);
713     for (i = 0; i < fp->bc; i++) sol_stor_body(fout, fp->bv + i);
714     for (i = 0; i < fp->hc; i++) sol_stor_item(fout, fp->hv + i);
715     for (i = 0; i < fp->zc; i++) sol_stor_goal(fout, fp->zv + i);
716     for (i = 0; i < fp->jc; i++) sol_stor_jump(fout, fp->jv + i);
717     for (i = 0; i < fp->xc; i++) sol_stor_swch(fout, fp->xv + i);
718     for (i = 0; i < fp->rc; i++) sol_stor_bill(fout, fp->rv + i);
719     for (i = 0; i < fp->uc; i++) sol_stor_ball(fout, fp->uv + i);
720     for (i = 0; i < fp->wc; i++) sol_stor_view(fout, fp->wv + i);
721     for (i = 0; i < fp->ic; i++) put_index(fout, fp->iv[i]);
722 }
723
724 int sol_stor_base(struct s_base *fp, const char *filename)
725 {
726     fs_file fout;
727
728     if ((fout = fs_open(filename, "w")))
729     {
730         sol_stor_file(fout, fp);
731         fs_close(fout);
732
733         return 1;
734     }
735     return 0;
736 }
737
738 /*---------------------------------------------------------------------------*/