sparselines.map: Re-texture level as per RlksNotes
[neverball] / share / solid.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.h"
20 #include "base_config.h"
21 #include "binary.h"
22 #include "common.h"
23 #include "fs.h"
24
25 enum
26 {
27     SOL_VER_MINIMUM = 6,
28     SOL_VER_PATH_FLAGS,
29     SOL_VER_CURRENT = SOL_VER_PATH_FLAGS
30 };
31
32 #define SOL_MAGIC (0xAF | 'S' << 8 | 'O' << 16 | 'L' << 24)
33
34 /*---------------------------------------------------------------------------*/
35
36 static int sol_version;
37
38 static int sol_file(fs_file fin)
39 {
40     int magic;
41     int version;
42
43     get_index(fin, &magic);
44     get_index(fin, &version);
45
46     if (magic != SOL_MAGIC || (version < SOL_VER_MINIMUM ||
47                                version > SOL_VER_CURRENT))
48         return 0;
49
50     sol_version = version;
51
52     return 1;
53 }
54
55 static void sol_load_mtrl(fs_file fin, struct s_mtrl *mp)
56 {
57     get_array(fin,  mp->d, 4);
58     get_array(fin,  mp->a, 4);
59     get_array(fin,  mp->s, 4);
60     get_array(fin,  mp->e, 4);
61     get_array(fin,  mp->h, 1);
62     get_index(fin, &mp->fl);
63
64     fs_read(mp->f, 1, PATHMAX, fin);
65 }
66
67 static void sol_load_vert(fs_file fin, struct s_vert *vp)
68 {
69     get_array(fin,  vp->p, 3);
70 }
71
72 static void sol_load_edge(fs_file fin, struct s_edge *ep)
73 {
74     get_index(fin, &ep->vi);
75     get_index(fin, &ep->vj);
76 }
77
78 static void sol_load_side(fs_file fin, struct s_side *sp)
79 {
80     get_array(fin,  sp->n, 3);
81     get_float(fin, &sp->d);
82 }
83
84 static void sol_load_texc(fs_file fin, struct s_texc *tp)
85 {
86     get_array(fin,  tp->u, 2);
87 }
88
89 static void sol_load_geom(fs_file fin, struct s_geom *gp)
90 {
91     get_index(fin, &gp->mi);
92     get_index(fin, &gp->ti);
93     get_index(fin, &gp->si);
94     get_index(fin, &gp->vi);
95     get_index(fin, &gp->tj);
96     get_index(fin, &gp->sj);
97     get_index(fin, &gp->vj);
98     get_index(fin, &gp->tk);
99     get_index(fin, &gp->sk);
100     get_index(fin, &gp->vk);
101 }
102
103 static void sol_load_lump(fs_file fin, struct s_lump *lp)
104 {
105     get_index(fin, &lp->fl);
106     get_index(fin, &lp->v0);
107     get_index(fin, &lp->vc);
108     get_index(fin, &lp->e0);
109     get_index(fin, &lp->ec);
110     get_index(fin, &lp->g0);
111     get_index(fin, &lp->gc);
112     get_index(fin, &lp->s0);
113     get_index(fin, &lp->sc);
114 }
115
116 static void sol_load_node(fs_file fin, struct s_node *np)
117 {
118     get_index(fin, &np->si);
119     get_index(fin, &np->ni);
120     get_index(fin, &np->nj);
121     get_index(fin, &np->l0);
122     get_index(fin, &np->lc);
123 }
124
125 static void sol_load_path(fs_file fin, struct s_path *pp)
126 {
127     get_array(fin,  pp->p, 3);
128     get_float(fin, &pp->t);
129     get_index(fin, &pp->pi);
130     get_index(fin, &pp->f);
131     get_index(fin, &pp->s);
132
133     pp->tm = TIME_TO_MS(pp->t);
134     pp->t  = MS_TO_TIME(pp->tm);
135
136     if (sol_version >= SOL_VER_PATH_FLAGS)
137         get_index(fin, &pp->fl);
138
139     pp->e[0] = 1.0f;
140     pp->e[1] = 0.0f;
141     pp->e[2] = 0.0f;
142     pp->e[3] = 0.0f;
143
144     if (pp->fl & P_ORIENTED)
145         get_array(fin, pp->e, 4);
146 }
147
148 static void sol_load_body(fs_file fin, struct s_body *bp)
149 {
150     get_index(fin, &bp->pi);
151     get_index(fin, &bp->ni);
152     get_index(fin, &bp->l0);
153     get_index(fin, &bp->lc);
154     get_index(fin, &bp->g0);
155     get_index(fin, &bp->gc);
156 }
157
158 static void sol_load_item(fs_file fin, struct s_item *hp)
159 {
160     get_array(fin,  hp->p, 3);
161     get_index(fin, &hp->t);
162     get_index(fin, &hp->n);
163 }
164
165 static void sol_load_goal(fs_file fin, struct s_goal *zp)
166 {
167     get_array(fin,  zp->p, 3);
168     get_float(fin, &zp->r);
169 }
170
171 static void sol_load_swch(fs_file fin, struct s_swch *xp)
172 {
173     get_array(fin,  xp->p, 3);
174     get_float(fin, &xp->r);
175     get_index(fin, &xp->pi);
176     get_float(fin, &xp->t0);
177     get_float(fin, &xp->t);
178     get_index(fin, &xp->f0);
179     get_index(fin, &xp->f);
180     get_index(fin, &xp->i);
181
182     xp->t0m = TIME_TO_MS(xp->t0);
183     xp->tm  = TIME_TO_MS(xp->t);
184
185     xp->t0 = MS_TO_TIME(xp->t0m);
186     xp->t  = MS_TO_TIME(xp->tm);
187 }
188
189 static void sol_load_bill(fs_file fin, struct s_bill *rp)
190 {
191     get_index(fin, &rp->fl);
192     get_index(fin, &rp->mi);
193     get_float(fin, &rp->t);
194     get_float(fin, &rp->d);
195     get_array(fin,  rp->w,  3);
196     get_array(fin,  rp->h,  3);
197     get_array(fin,  rp->rx, 3);
198     get_array(fin,  rp->ry, 3);
199     get_array(fin,  rp->rz, 3);
200     get_array(fin,  rp->p,  3);
201 }
202
203 static void sol_load_jump(fs_file fin, struct s_jump *jp)
204 {
205     get_array(fin,  jp->p, 3);
206     get_array(fin,  jp->q, 3);
207     get_float(fin, &jp->r);
208 }
209
210 static void sol_load_ball(fs_file fin, struct s_ball *bp)
211 {
212     get_array(fin,  bp->p, 3);
213     get_float(fin, &bp->r);
214
215     bp->e[0][0] = bp->E[0][0] = 1.0f;
216     bp->e[0][1] = bp->E[0][1] = 0.0f;
217     bp->e[0][2] = bp->E[0][2] = 0.0f;
218
219     bp->e[1][0] = bp->E[1][0] = 0.0f;
220     bp->e[1][1] = bp->E[1][1] = 1.0f;
221     bp->e[1][2] = bp->E[1][2] = 0.0f;
222
223     bp->e[2][0] = bp->E[2][0] = 0.0f;
224     bp->e[2][1] = bp->E[2][1] = 0.0f;
225     bp->e[2][2] = bp->E[2][2] = 1.0f;
226 }
227
228 static void sol_load_view(fs_file fin, struct s_view *wp)
229 {
230     get_array(fin,  wp->p, 3);
231     get_array(fin,  wp->q, 3);
232 }
233
234 static void sol_load_dict(fs_file fin, struct s_dict *dp)
235 {
236     get_index(fin, &dp->ai);
237     get_index(fin, &dp->aj);
238 }
239
240 static void sol_load_indx(fs_file fin, struct s_file *fp)
241 {
242     get_index(fin, &fp->ac);
243     get_index(fin, &fp->dc);
244     get_index(fin, &fp->mc);
245     get_index(fin, &fp->vc);
246     get_index(fin, &fp->ec);
247     get_index(fin, &fp->sc);
248     get_index(fin, &fp->tc);
249     get_index(fin, &fp->gc);
250     get_index(fin, &fp->lc);
251     get_index(fin, &fp->nc);
252     get_index(fin, &fp->pc);
253     get_index(fin, &fp->bc);
254     get_index(fin, &fp->hc);
255     get_index(fin, &fp->zc);
256     get_index(fin, &fp->jc);
257     get_index(fin, &fp->xc);
258     get_index(fin, &fp->rc);
259     get_index(fin, &fp->uc);
260     get_index(fin, &fp->wc);
261     get_index(fin, &fp->ic);
262 }
263
264 static int sol_load_file(fs_file fin, struct s_file *fp)
265 {
266     int i;
267
268     if (!sol_file(fin))
269         return 0;
270
271     sol_load_indx(fin, fp);
272
273     if (fp->ac)
274         fp->av = (char          *) calloc(fp->ac, sizeof (char));
275     if (fp->mc)
276         fp->mv = (struct s_mtrl *) calloc(fp->mc, sizeof (struct s_mtrl));
277     if (fp->vc)
278         fp->vv = (struct s_vert *) calloc(fp->vc, sizeof (struct s_vert));
279     if (fp->ec)
280         fp->ev = (struct s_edge *) calloc(fp->ec, sizeof (struct s_edge));
281     if (fp->sc)
282         fp->sv = (struct s_side *) calloc(fp->sc, sizeof (struct s_side));
283     if (fp->tc)
284         fp->tv = (struct s_texc *) calloc(fp->tc, sizeof (struct s_texc));
285     if (fp->gc)
286         fp->gv = (struct s_geom *) calloc(fp->gc, sizeof (struct s_geom));
287     if (fp->lc)
288         fp->lv = (struct s_lump *) calloc(fp->lc, sizeof (struct s_lump));
289     if (fp->nc)
290         fp->nv = (struct s_node *) calloc(fp->nc, sizeof (struct s_node));
291     if (fp->pc)
292         fp->pv = (struct s_path *) calloc(fp->pc, sizeof (struct s_path));
293     if (fp->bc)
294         fp->bv = (struct s_body *) calloc(fp->bc, sizeof (struct s_body));
295     if (fp->hc)
296         fp->hv = (struct s_item *) calloc(fp->hc, sizeof (struct s_item));
297     if (fp->zc)
298         fp->zv = (struct s_goal *) calloc(fp->zc, sizeof (struct s_goal));
299     if (fp->jc)
300         fp->jv = (struct s_jump *) calloc(fp->jc, sizeof (struct s_jump));
301     if (fp->xc)
302         fp->xv = (struct s_swch *) calloc(fp->xc, sizeof (struct s_swch));
303     if (fp->rc)
304         fp->rv = (struct s_bill *) calloc(fp->rc, sizeof (struct s_bill));
305     if (fp->uc)
306         fp->uv = (struct s_ball *) calloc(fp->uc, sizeof (struct s_ball));
307     if (fp->wc)
308         fp->wv = (struct s_view *) calloc(fp->wc, sizeof (struct s_view));
309     if (fp->dc)
310         fp->dv = (struct s_dict *) calloc(fp->dc, sizeof (struct s_dict));
311     if (fp->ic)
312         fp->iv = (int           *) calloc(fp->ic, sizeof (int));
313
314     if (fp->ac)
315         fs_read(fp->av, 1, fp->ac, fin);
316
317     for (i = 0; i < fp->dc; i++) sol_load_dict(fin, fp->dv + i);
318     for (i = 0; i < fp->mc; i++) sol_load_mtrl(fin, fp->mv + i);
319     for (i = 0; i < fp->vc; i++) sol_load_vert(fin, fp->vv + i);
320     for (i = 0; i < fp->ec; i++) sol_load_edge(fin, fp->ev + i);
321     for (i = 0; i < fp->sc; i++) sol_load_side(fin, fp->sv + i);
322     for (i = 0; i < fp->tc; i++) sol_load_texc(fin, fp->tv + i);
323     for (i = 0; i < fp->gc; i++) sol_load_geom(fin, fp->gv + i);
324     for (i = 0; i < fp->lc; i++) sol_load_lump(fin, fp->lv + i);
325     for (i = 0; i < fp->nc; i++) sol_load_node(fin, fp->nv + i);
326     for (i = 0; i < fp->pc; i++) sol_load_path(fin, fp->pv + i);
327     for (i = 0; i < fp->bc; i++) sol_load_body(fin, fp->bv + i);
328     for (i = 0; i < fp->hc; i++) sol_load_item(fin, fp->hv + i);
329     for (i = 0; i < fp->zc; i++) sol_load_goal(fin, fp->zv + i);
330     for (i = 0; i < fp->jc; i++) sol_load_jump(fin, fp->jv + i);
331     for (i = 0; i < fp->xc; i++) sol_load_swch(fin, fp->xv + i);
332     for (i = 0; i < fp->rc; i++) sol_load_bill(fin, fp->rv + i);
333     for (i = 0; i < fp->uc; i++) sol_load_ball(fin, fp->uv + i);
334     for (i = 0; i < fp->wc; i++) sol_load_view(fin, fp->wv + i);
335     for (i = 0; i < fp->ic; i++) get_index(fin, fp->iv + i);
336
337     return 1;
338 }
339
340 static int sol_load_head(fs_file fin, struct s_file *fp)
341 {
342     if (!sol_file(fin))
343         return 0;
344
345     sol_load_indx(fin, fp);
346
347     if (fp->ac)
348     {
349         fp->av = (char *) calloc(fp->ac, sizeof (char));
350         fs_read(fp->av, 1, fp->ac, fin);
351     }
352
353     if (fp->dc)
354     {
355         int i;
356
357         fp->dv = (struct s_dict *) calloc(fp->dc, sizeof (struct s_dict));
358
359         for (i = 0; i < fp->dc; i++)
360             sol_load_dict(fin, fp->dv + i);
361     }
362
363     return 1;
364 }
365
366 int sol_load_only_file(struct s_file *fp, const char *filename)
367 {
368     fs_file fin;
369     int res = 0;
370
371     if ((fin = fs_open(filename, "r")))
372     {
373         res = sol_load_file(fin, fp);
374         fs_close(fin);
375     }
376     return res;
377 }
378
379 int sol_load_only_head(struct s_file *fp, const char *filename)
380 {
381     fs_file fin;
382     int res = 0;
383
384     if ((fin = fs_open(filename, "r")))
385     {
386         res = sol_load_head(fin, fp);
387         fs_close(fin);
388     }
389     return res;
390 }
391
392 /*---------------------------------------------------------------------------*/
393
394 static void sol_stor_mtrl(fs_file fout, struct s_mtrl *mp)
395 {
396     put_array(fout, mp->d, 4);
397     put_array(fout, mp->a, 4);
398     put_array(fout, mp->s, 4);
399     put_array(fout, mp->e, 4);
400     put_array(fout, mp->h, 1);
401     put_index(fout, mp->fl);
402
403     fs_write(mp->f, 1, PATHMAX, fout);
404 }
405
406 static void sol_stor_vert(fs_file fout, struct s_vert *vp)
407 {
408     put_array(fout,  vp->p, 3);
409 }
410
411 static void sol_stor_edge(fs_file fout, struct s_edge *ep)
412 {
413     put_index(fout, ep->vi);
414     put_index(fout, ep->vj);
415 }
416
417 static void sol_stor_side(fs_file fout, struct s_side *sp)
418 {
419     put_array(fout, sp->n, 3);
420     put_float(fout, sp->d);
421 }
422
423 static void sol_stor_texc(fs_file fout, struct s_texc *tp)
424 {
425     put_array(fout,  tp->u, 2);
426 }
427
428 static void sol_stor_geom(fs_file fout, struct s_geom *gp)
429 {
430     put_index(fout, gp->mi);
431     put_index(fout, gp->ti);
432     put_index(fout, gp->si);
433     put_index(fout, gp->vi);
434     put_index(fout, gp->tj);
435     put_index(fout, gp->sj);
436     put_index(fout, gp->vj);
437     put_index(fout, gp->tk);
438     put_index(fout, gp->sk);
439     put_index(fout, gp->vk);
440 }
441
442 static void sol_stor_lump(fs_file fout, struct s_lump *lp)
443 {
444     put_index(fout, lp->fl);
445     put_index(fout, lp->v0);
446     put_index(fout, lp->vc);
447     put_index(fout, lp->e0);
448     put_index(fout, lp->ec);
449     put_index(fout, lp->g0);
450     put_index(fout, lp->gc);
451     put_index(fout, lp->s0);
452     put_index(fout, lp->sc);
453 }
454
455 static void sol_stor_node(fs_file fout, struct s_node *np)
456 {
457     put_index(fout, np->si);
458     put_index(fout, np->ni);
459     put_index(fout, np->nj);
460     put_index(fout, np->l0);
461     put_index(fout, np->lc);
462 }
463
464 static void sol_stor_path(fs_file fout, struct s_path *pp)
465 {
466     put_array(fout, pp->p, 3);
467     put_float(fout, pp->t);
468     put_index(fout, pp->pi);
469     put_index(fout, pp->f);
470     put_index(fout, pp->s);
471     put_index(fout, pp->fl);
472
473     if (pp->fl & P_ORIENTED)
474         put_array(fout, pp->e, 4);
475 }
476
477 static void sol_stor_body(fs_file fout, struct s_body *bp)
478 {
479     put_index(fout, bp->pi);
480     put_index(fout, bp->ni);
481     put_index(fout, bp->l0);
482     put_index(fout, bp->lc);
483     put_index(fout, bp->g0);
484     put_index(fout, bp->gc);
485 }
486
487 static void sol_stor_item(fs_file fout, struct s_item *hp)
488 {
489     put_array(fout, hp->p, 3);
490     put_index(fout, hp->t);
491     put_index(fout, hp->n);
492 }
493
494 static void sol_stor_goal(fs_file fout, struct s_goal *zp)
495 {
496     put_array(fout, zp->p, 3);
497     put_float(fout, zp->r);
498 }
499
500 static void sol_stor_swch(fs_file fout, struct s_swch *xp)
501 {
502     put_array(fout, xp->p, 3);
503     put_float(fout, xp->r);
504     put_index(fout, xp->pi);
505     put_float(fout, xp->t0);
506     put_float(fout, xp->t);
507     put_index(fout, xp->f0);
508     put_index(fout, xp->f);
509     put_index(fout, xp->i);
510 }
511
512 static void sol_stor_bill(fs_file fout, struct s_bill *rp)
513 {
514     put_index(fout, rp->fl);
515     put_index(fout, rp->mi);
516     put_float(fout, rp->t);
517     put_float(fout, rp->d);
518     put_array(fout, rp->w,  3);
519     put_array(fout, rp->h,  3);
520     put_array(fout, rp->rx, 3);
521     put_array(fout, rp->ry, 3);
522     put_array(fout, rp->rz, 3);
523     put_array(fout, rp->p,  3);
524 }
525
526 static void sol_stor_jump(fs_file fout, struct s_jump *jp)
527 {
528     put_array(fout, jp->p, 3);
529     put_array(fout, jp->q, 3);
530     put_float(fout, jp->r);
531 }
532
533 static void sol_stor_ball(fs_file fout, struct s_ball *bp)
534 {
535     put_array(fout, bp->p, 3);
536     put_float(fout, bp->r);
537 }
538
539 static void sol_stor_view(fs_file fout, struct s_view *wp)
540 {
541     put_array(fout,  wp->p, 3);
542     put_array(fout,  wp->q, 3);
543 }
544
545 static void sol_stor_dict(fs_file fout, struct s_dict *dp)
546 {
547     put_index(fout, dp->ai);
548     put_index(fout, dp->aj);
549 }
550
551 static void sol_stor_file(fs_file fout, struct s_file *fp)
552 {
553     int i;
554     int magic   = SOL_MAGIC;
555     int version = SOL_VER_CURRENT;
556
557     put_index(fout, magic);
558     put_index(fout, version);
559
560     put_index(fout, fp->ac);
561     put_index(fout, fp->dc);
562     put_index(fout, fp->mc);
563     put_index(fout, fp->vc);
564     put_index(fout, fp->ec);
565     put_index(fout, fp->sc);
566     put_index(fout, fp->tc);
567     put_index(fout, fp->gc);
568     put_index(fout, fp->lc);
569     put_index(fout, fp->nc);
570     put_index(fout, fp->pc);
571     put_index(fout, fp->bc);
572     put_index(fout, fp->hc);
573     put_index(fout, fp->zc);
574     put_index(fout, fp->jc);
575     put_index(fout, fp->xc);
576     put_index(fout, fp->rc);
577     put_index(fout, fp->uc);
578     put_index(fout, fp->wc);
579     put_index(fout, fp->ic);
580
581     fs_write(fp->av, 1, fp->ac, fout);
582
583     for (i = 0; i < fp->dc; i++) sol_stor_dict(fout, fp->dv + i);
584     for (i = 0; i < fp->mc; i++) sol_stor_mtrl(fout, fp->mv + i);
585     for (i = 0; i < fp->vc; i++) sol_stor_vert(fout, fp->vv + i);
586     for (i = 0; i < fp->ec; i++) sol_stor_edge(fout, fp->ev + i);
587     for (i = 0; i < fp->sc; i++) sol_stor_side(fout, fp->sv + i);
588     for (i = 0; i < fp->tc; i++) sol_stor_texc(fout, fp->tv + i);
589     for (i = 0; i < fp->gc; i++) sol_stor_geom(fout, fp->gv + i);
590     for (i = 0; i < fp->lc; i++) sol_stor_lump(fout, fp->lv + i);
591     for (i = 0; i < fp->nc; i++) sol_stor_node(fout, fp->nv + i);
592     for (i = 0; i < fp->pc; i++) sol_stor_path(fout, fp->pv + i);
593     for (i = 0; i < fp->bc; i++) sol_stor_body(fout, fp->bv + i);
594     for (i = 0; i < fp->hc; i++) sol_stor_item(fout, fp->hv + i);
595     for (i = 0; i < fp->zc; i++) sol_stor_goal(fout, fp->zv + i);
596     for (i = 0; i < fp->jc; i++) sol_stor_jump(fout, fp->jv + i);
597     for (i = 0; i < fp->xc; i++) sol_stor_swch(fout, fp->xv + i);
598     for (i = 0; i < fp->rc; i++) sol_stor_bill(fout, fp->rv + i);
599     for (i = 0; i < fp->uc; i++) sol_stor_ball(fout, fp->uv + i);
600     for (i = 0; i < fp->wc; i++) sol_stor_view(fout, fp->wv + i);
601     for (i = 0; i < fp->ic; i++) put_index(fout, fp->iv[i]);
602 }
603
604 /*---------------------------------------------------------------------------*/
605
606 int sol_stor(struct s_file *fp, const char *filename)
607 {
608     fs_file fout;
609
610     if ((fout = fs_open(filename, "w")))
611     {
612         sol_stor_file(fout, fp);
613         fs_close(fout);
614
615         return 1;
616     }
617     return 0;
618 }
619
620 void sol_free(struct s_file *fp)
621 {
622     if (fp->av) free(fp->av);
623     if (fp->mv) free(fp->mv);
624     if (fp->vv) free(fp->vv);
625     if (fp->ev) free(fp->ev);
626     if (fp->sv) free(fp->sv);
627     if (fp->tv) free(fp->tv);
628     if (fp->gv) free(fp->gv);
629     if (fp->lv) free(fp->lv);
630     if (fp->nv) free(fp->nv);
631     if (fp->pv) free(fp->pv);
632     if (fp->bv) free(fp->bv);
633     if (fp->hv) free(fp->hv);
634     if (fp->zv) free(fp->zv);
635     if (fp->jv) free(fp->jv);
636     if (fp->xv) free(fp->xv);
637     if (fp->rv) free(fp->rv);
638     if (fp->uv) free(fp->uv);
639     if (fp->wv) free(fp->wv);
640     if (fp->dv) free(fp->dv);
641     if (fp->iv) free(fp->iv);
642
643     memset(fp, 0, sizeof (struct s_file));
644 }
645
646 /*---------------------------------------------------------------------------*/