source: abuse/trunk/src/newlight.cpp @ 129

Last change on this file since 129 was 129, checked in by Sam Hocevar, 15 years ago
  • Get rid of jmalloc and replace it with standard malloc. Modern operating systems certainly perform a lot better than this custom implementation, and we have superior tools (eg. valgrind) to debug and profile memory usage without interfering with the code itself.
File size: 20.1 KB
Line 
1/*
2 *  Abuse - dark 2D side-scrolling platform game
3 *  Copyright (c) 1995 Crack dot Com
4 *
5 *  This software was released into the Public Domain. As with most public
6 *  domain software, no warranty is made or implied by Crack dot Com or
7 *  Jonathan Clark.
8 */
9
10#include "config.h"
11
12#include <stdlib.h>
13
14#include "light.hpp"
15#include "image.hpp"
16#include "macs.hpp"
17#include "video.hpp"
18#include "palette.hpp"
19#include "timing.hpp"
20#include "specs.hpp"
21#include "dprint.hpp"
22#include "filter.hpp"
23#include "video.hpp"
24
25light_source *first_light_source=NULL;
26unsigned char *white_light,*green_light;
27unsigned short min_light_level=0;
28extern int vmode;
29
30int light_detail=MEDIUM_DETAIL;
31
32long light_to_number(light_source *l)
33{
34    if( !l ) return 0;
35    int x = 1;
36    light_source *s;
37    for (s = first_light_source; s; s = s->next, x++)
38        if (s == l) return x;
39    return 0;
40}
41
42
43light_source *number_to_light(long x)
44{
45    if (x == 0) return NULL;
46    x--;
47    light_source *s;
48    for (s = first_light_source; x && s; x--, s = s->next);
49    return s;
50}
51
52light_source *light_source::copy()
53{
54    next = new light_source(type,x,y,inner_radius,outer_radius,xshift,yshift,next);
55    return next;
56}
57
58void delete_all_lights()
59{
60    while (first_light_source)
61    {
62        light_source *p = first_light_source;
63        first_light_source = first_light_source->next;
64        delete p;
65    }
66}
67
68void delete_light(light_source *which)
69{
70  if (which==first_light_source)
71  {
72    first_light_source=first_light_source->next;
73    delete which;
74  }
75  else
76  {
77    for (light_source *f=first_light_source;f->next!=which && f;f=f->next);
78    if (f)
79    {
80      f->next=which->next;
81      delete which;
82    }
83  }
84}
85
86void light_source::calc_range()
87{
88  switch (type)
89  {
90    case 0 :
91    { x1=x-(outer_radius>>xshift); y1=y-(outer_radius>>yshift);
92      x2=x+(outer_radius>>xshift); y2=y+(outer_radius>>yshift);
93    } break;
94    case 1 :
95    { x1=x-(outer_radius>>xshift); y1=y-(outer_radius>>yshift);
96      x2=x+(outer_radius>>xshift); y2=y;
97    } break;
98    case 2 :
99    { x1=x-(outer_radius>>xshift); y1=y;
100      x2=x+(outer_radius>>xshift); y2=y+(outer_radius>>yshift);
101    } break;
102    case 3 :
103    { x1=x; y1=y-(outer_radius>>yshift);
104      x2=x+(outer_radius>>xshift); y2=y+(outer_radius>>yshift);
105    } break;
106    case 4 :
107    { x1=x-(outer_radius>>xshift); y1=y-(outer_radius>>yshift);
108      x2=x; y2=y+(outer_radius>>yshift);
109    } break;
110
111
112    case 5 :
113    { x1=x; y1=y-(outer_radius>>yshift);
114      x2=x+(outer_radius>>xshift); y2=y;
115    } break;
116    case 6 :
117    { x1=x-(outer_radius>>xshift); y1=y-(outer_radius>>yshift);
118      x2=x; y2=y;
119    } break;
120    case 7 :
121    { x1=x-(outer_radius>>xshift); y1=y;
122      x2=x; y2=y+(outer_radius>>yshift);
123    } break;
124    case 8 :
125    { x1=x; y1=y;
126      x2=x+(outer_radius>>xshift); y2=y+(outer_radius>>yshift);
127    } break;
128    case 9 :
129    {
130      x1=x;
131      y1=y;
132      x2=x+xshift;
133      y2=y+yshift;
134    } break;
135
136  }
137  mul_div=(1<<16)/(outer_radius-inner_radius)*64;
138}
139
140light_source::light_source(char Type, long X, long Y, long Inner_radius,
141               long Outer_radius, long Xshift,  long Yshift, light_source *Next)
142{
143  type=Type;
144  x=X; y=Y;
145  inner_radius=Inner_radius;
146  outer_radius=Outer_radius;
147  next=Next;
148  known=0;
149  xshift=Xshift;
150  yshift=Yshift;
151  calc_range();
152}
153
154light_source *add_light_source(char type, long x, long y,
155                   long inner, long outer, long xshift, long yshift)
156{
157    first_light_source = new light_source(type,x,y,inner,outer,xshift,yshift,first_light_source);
158    return first_light_source;
159}
160
161
162#define TTINTS 9
163uchar *tints[TTINTS];
164
165void calc_tint(uchar *tint, int rs, int gs, int bs, int ra, int ga, int ba, palette *pal)
166{
167  palette npal;
168  memset(npal.addr(),0,256);
169
170  for (int i=0;i<256;i++)
171  {
172    npal.set(i,(int)rs,(int)gs,(int)bs);
173    rs+=ra; if (rs>255) rs=255; if (rs<0) rs=0;
174    gs+=ga; if (gs>255) gs=255; if (gs<0) gs=0;
175    bs+=ba; if (bs>255) bs=255; if (bs<0) bs=0;
176  }
177  filter f(pal,&npal);
178  filter f2(&npal,pal);
179
180  for (i=0;i<256;i++,tint++)
181    *tint=f2.get_mapping(f.get_mapping(i));
182}
183
184
185void calc_light_table(palette *pal)
186{
187  white_light=(unsigned char *)malloc(256*64);
188  green_light=(unsigned char *)malloc(256*64);
189  for (int i=0;i<TTINTS;i++)
190      tints[i]=(uchar *)malloc(256);
191
192  jFILE fp("light.tbl","rb");
193  int recalc=0;
194  if (fp.open_failure()) recalc=1;
195  else
196  {
197    if (fp.read_uint16()!=calc_crc((unsigned char *)pal->addr(),768))
198      recalc=1;
199    else
200    {
201      fp.read(white_light,256*64);
202      fp.read(green_light,256*64);
203      for (i=0;i<TTINTS;i++)
204        fp.read(tints[i],256);
205    }
206  }
207
208  if (recalc)
209  {
210    fprintf(stderr,"Palette has changed, recalculating light table...\n");
211    fprintf(stderr,"white : ");
212    for (int color=0;color<256;color++)
213    {
214      unsigned char r,g,b;
215      pal->get(color,r,g,b);
216      if (color%16==0)
217        fprintf(stderr,"%d ",color);
218      for (int intensity=63;intensity>=0;intensity--)
219      {
220    if (r>0 || g>0 || b>0)
221          white_light[intensity*256+color]=pal->find_closest(r,g,b);
222    else
223          white_light[intensity*256+color]=0;
224    if (r) r--;  if (g) g--;  if (b) b--;     
225      }
226    }
227
228    fprintf(stderr,"green : ");
229    for (color=0;color<256;color++)
230    {
231      unsigned char r,g,b;
232      pal->get(color,r,g,b);
233      r=r*3/5; b=b*3/5; g+=7; if (g>255) g=255;
234      if (color%16==0)
235        fprintf(stderr,"%d ",color);
236      for (int intensity=63;intensity>=0;intensity--)
237      {
238    if (r>0 || g>0 || b>0)
239          green_light[intensity*256+color]=pal->find_closest(r,g,b);
240    else
241          green_light[intensity*256+color]=0;
242    if (r) r--;
243    if ((intensity&1)==1)
244      if (g) g--;
245    if (b) b--;     
246      }
247    }
248
249    dprintf("\ncalculating tints : \n");
250    uchar t[TTINTS*6]={0,0,0,0,0,0, // normal
251                   0,0,0,1,0,0,     // red
252           0,0,0,1,1,0,     // yellow
253           0,0,0,1,0,1,     // purple
254           0,0,0,1,1,1,     // gray
255           0,0,0,0,1,0,     // green
256           0,0,0,0,0,1,     // blue
257           0,0,0,0,1,1,     // cyan
258
259
260
261
262
263
264           0,0,0,0,0,0   // reverse green  (night vision effect)
265         } ;
266    uchar *ti=t+6;
267    uchar *c;
268    for (i=0,c=tints[0];i<256;i++,c++) *c=i;  // make the normal tint (maps everthing to itself)
269    for (i=0,c=tints[TTINTS-1];i<256;i++,c++)  // reverse green
270    {
271      int r=pal->red(i)/2,g=255-pal->green(i)-30,b=pal->blue(i)*3/5+50;
272      if (g<0) g=0;
273      if (b>255) b=0;
274      *c=pal->find_closest(r,g,b);
275    }
276
277    // make the colored tints
278    for (i=1;i<TTINTS-1;i++)
279    {
280      calc_tint(tints[i],ti[0],ti[1],ti[2],ti[3],ti[4],ti[5],pal);
281      ti+=6;
282    }
283
284
285
286    jFILE f("light.tbl","wb");
287    f.write_uint16(calc_crc((unsigned char *)pal->addr(),768));
288    f.write(white_light,256*64);
289    f.write(green_light,256*64);
290    for (int i=0;i<TTINTS;i++)
291      f.write(tints[i],256);
292  }
293}
294
295
296light_patch *light_patch::copy(light_patch *Next)
297{
298  light_patch *p=new light_patch(x1,y1,x2,y2,Next);
299  p->total=total;
300  if (total)
301  {
302    p->lights=(light_source **)malloc(total*sizeof(light_source *));
303    memcpy(p->lights,lights,total*(sizeof(light_source *)));
304  }
305  else
306    p->lights=NULL;
307  return p;
308}
309
310#define MAX_LP 10
311
312
313void add_light(light_patch *&first, long x1, long y1, long x2, long y2,
314                light_source *who)
315{
316  light_patch *last=NULL;
317  for (light_patch *p=first;p;p=p->next)
318  {
319    // first see if light patch we are adding is enclosed entirely by another patch
320    if (x1>=p->x1 && y1>=p->y1 && x2<=p->x2 && y2<=p->y2)
321    {
322      if (p->total==MAX_LP) return ;
323
324      if (x1>p->x1)
325      {
326    first=p->copy(first);
327    first->x2=x1-1;
328      }
329      if (x2<p->x2)
330      {
331    first=p->copy(first);
332    first->x1=x2+1;
333      }
334      if (y1>p->y1)
335      {
336    first=p->copy(first);
337    first->x1=x1;
338    first->x2=x2;
339    first->y2=y1-1;
340      }
341      if (y2<p->y2)
342      {
343    first=p->copy(first);
344    first->x1=x1;
345    first->x2=x2;
346    first->y1=y2+1;
347      }
348      p->x1=x1; p->y1=y1; p->x2=x2; p->y2=y2;
349      p->total++;
350      p->lights=(light_source **)realloc(p->lights,sizeof(light_source *)*p->total);
351      p->lights[p->total-1]=who;
352      return ;
353    }
354
355    // see if the patch completly covers another patch.
356    if (x1<=p->x1 && y1<=p->y1 && x2>=p->x2 && y2>=p->y2)
357    {
358      if (x1<p->x1)
359        add_light(first,x1,y1,p->x1-1,y2,who);
360      if (x2>p->x2)
361        add_light(first,p->x2+1,y1,x2,y2,who);
362      if (y1<p->y1)
363        add_light(first,p->x1,y1,p->x2,p->y1-1,who);
364      if (y2>p->y2)
365        add_light(first,p->x1,p->y2+1,p->x2,y2,who);
366      if (p->total==MAX_LP)  return ;
367      p->total++;
368      p->lights=(light_source **)realloc(p->lights,sizeof(light_source *)*p->total);
369      p->lights[p->total-1]=who;
370      return ;
371    }
372
373    // see if we intersect another rect
374    if (!(x2<p->x1 || y2<p->y1 || x1>p->x2 || y1>p->y2))
375    {
376      int ax1,ay1,ax2,ay2;
377      if (x1<p->x1)
378      {
379        add_light(first,x1,max(y1,p->y1),p->x1-1,min(y2,p->y2),who);
380    ax1=p->x1;
381      } else
382    ax1=x1;
383
384      if (x2>p->x2)
385      {
386        add_light(first,p->x2+1,max(y1,p->y1),x2,min(y2,p->y2),who);
387    ax2=p->x2;
388      }
389      else
390    ax2=x2;
391
392      if (y1<p->y1)
393      {
394        add_light(first,x1,y1,x2,p->y1-1,who);
395    ay1=p->y1;
396      } else
397    ay1=y1;
398
399      if (y2>p->y2)
400      {
401        add_light(first,x1,p->y2+1,x2,y2,who);
402    ay2=p->y2;
403      } else
404    ay2=y2;
405
406
407      add_light(first,ax1,ay1,ax2,ay2,who);
408
409      return ;
410    }
411  }
412}
413
414light_patch *find_patch(int screenx, int screeny, light_patch *list)
415{
416  for (;list;list=list->next)
417  {
418    if (screenx>=list->x1 && screenx<=list->x2 && screeny>=list->y1 && screeny<=list->y2)
419      return list;
420  }
421  return NULL;
422}
423
424int calc_light_value(long x, long y, light_patch *which)
425{
426  int lv=0;
427  int t=which->total;
428  for (register int i=t-1;i>=0;i--)
429  {
430    light_source *fn=which->lights[i];
431    if (fn->type==9)
432    {
433      lv=fn->inner_radius;
434      i=0;
435    }
436    else
437    {
438      long dx=abs(fn->x-x)<<fn->xshift;
439      long dy=abs(fn->y-y)<<fn->yshift;
440      long  r2;
441      if (dx<dy)
442        r2=dx+dy-(dx>>1);
443      else r2=dx+dy-(dy>>1);
444
445      if (r2>=fn->inner_radius)
446      {
447    if (r2<fn->outer_radius)
448    {
449      lv+=((fn->outer_radius-r2)*fn->mul_div)>>16;
450    }
451      } else lv=63;   
452    }
453  }
454  if (lv>63) return 63;
455  else
456    return lv;
457}
458
459
460void reduce_patches(light_patch *f)   // find constant valued patches
461{
462
463}
464
465light_patch *make_patch_list(int cx1,int cy1,int cx2,int cy2, long screenx, long screeny)
466{
467  light_patch *first=new light_patch(cx1,cy1,cx2,cy2,NULL);
468
469  for (light_source *f=first_light_source;f;f=f->next)   // determine which lights will have effect
470  {
471    long x1=f->x1-screenx,y1=f->y1-screeny,x2=f->x2-screenx,y2=f->y2-screeny;
472    if (x1<cx1) x1=cx1;
473    if (y1<cy1) y1=cy1;
474    if (x2>cx2) x2=cx2;
475    if (y2>cy2) y2=cy2;
476
477    if (x1<=x2 && y1<=y2)
478      add_light(first,x1,y1,x2,y2,f);
479  }
480  reduce_patches(first);
481
482  return first;
483}
484
485void delete_patch_list(light_patch *first)
486{
487  while (first)
488  {
489    light_patch *p=first;
490    first=first->next;
491    delete p;
492  }
493}
494
495
496inline long MAP_PUT(long pad, long screen_addr, long remap, long w)
497{ while (w--)
498  {
499    *((uchar *)(screen_addr))=*((uchar *)remap+*((uchar *)screen_addr));
500    screen_addr++;
501  }
502  return screen_addr;
503}
504
505inline long MAP_PUT2(long dest_addr, long screen_addr, long remap, long w)
506{ while (w--)
507  {
508    *((uchar *)(dest_addr))=*((uchar *)remap+*((uchar *)screen_addr));
509    screen_addr++;
510    dest_addr++;
511  }
512  return dest_addr;
513}
514
515inline long calc_lv(light_patch *lp, long sx, long sy)
516{
517  light_source **lon_p=lp->lights;
518  long lv=min_light_level;
519  int light_on;
520  for (light_on=lp->total-1;light_on>=0;light_on--)
521  {
522    light_source *fn=*lon_p;
523    long *dt=&(*lon_p)->type;
524    if (*dt==9)
525    {
526      lv=fn->inner_radius;
527      light_on=0;   
528    } else
529    {
530      dt++;
531      int dx=abs(*dt-sx); dt++;
532      dx<<=*dt;  dt++;
533
534      int dy=abs(*dt-sy); dt++;
535      dy<<=*dt;  dt++;
536
537      int r2;
538      if (dx<dy)
539      r2=dx+dy-(dx>>1);
540      else r2=dx+dy-(dy>>1);
541
542      if (r2<*dt)
543      {       
544    int v=*dt-r2; dt++;       
545    lv+=v*(*dt)>>16;
546      }
547    }
548    lon_p++;
549  }
550  if (lv>63) return 63;
551  else return lv;
552
553}
554
555
556void light_screen(image *sc, long screenx, long screeny, uchar *light_lookup)
557{
558  int lx_run,ly_run;
559  switch (light_detail)
560  {
561    case HIGH_DETAIL :
562    { lx_run=2; ly_run=1; } break;
563    case MEDIUM_DETAIL :
564    { lx_run=3; ly_run=2; } break;
565    case LOW_DETAIL :
566    { lx_run=4; ly_run=3; } break;
567    case POOR_DETAIL :                   // low detail lighting alread taken care of.
568    return ;
569  }
570
571  short cx1,cy1,cx2,cy2;
572  sc->get_clip(cx1,cy1,cx2,cy2);
573//  sc->add_dirty(cx1,cy1,cx2,cy2);
574  unsigned char *mint=light_lookup+min_light_level*256;
575  screenx-=cx1;
576  screeny-=cy1;
577
578
579  light_patch *first=make_patch_list(cx1,cy1,cx2,cy2,screenx,screeny);
580
581
582  int ytry=(1<<ly_run),xtry=(1<<lx_run);
583  int calcx_mask=(0xefffffff-(xtry-1));
584  int calcy_mask=(0xefffffff-(ytry-1));
585  int scr_w=screen->width();
586
587  for (light_patch *lp=first;lp;lp=lp->next)
588  {
589    register int x2=lp->x2;
590    if (lp->total==0)  // do dark patches really fast.
591    {
592      unsigned char *sl=screen->scan_line(lp->y1)+lp->x1,*dest;
593      dest=sl;
594
595      int y2=lp->y2;
596      for (int y=lp->y1;y<=y2;y++,sl+=scr_w,dest+=scr_w)
597      {
598    int w=lp->x2-lp->x1+1;
599        MAP_PUT2((long)dest,(long)sl,(long)mint,w);
600      }
601    }
602    else
603    {
604      int todoy;
605      int y2=lp->y2;
606
607      int xmask=(xtry-1);
608      int ymask=(ytry-1);
609
610      uchar *yaddr=screen->scan_line(lp->y1)+lp->x1,*dyaddr;
611      dyaddr=yaddr;
612
613      for (int y=lp->y1;y<=y2;)
614      {
615    long sy=(screeny+y);
616    if (y+ytry>lp->y2)        // see how many y lines to do for this block
617      todoy=lp->y2-y+1;
618    else todoy=ytry;
619    int maxy=ytry-(sy&ymask);
620    if (todoy>maxy)
621      todoy=maxy;
622   
623    uchar *xaddr=yaddr,*dxaddr=dyaddr;
624    for (register int x=lp->x1;x<=x2;)
625    {
626      long lv=min_light_level;
627      unsigned char *ct;
628      light_source *f;
629      int todox;
630      if (x+xtry>lp->x2)
631        todox=lp->x2-x+1;
632      else todox=xtry;
633      int sx=(screenx+x);
634      int max=xtry-(sx&xmask);
635      if (todox>max)
636        todox=max;
637
638
639      ct=light_lookup+calc_lv(lp,sx,sy)*256;
640      switch (todox)
641      {
642        case 8 :
643        {
644          x+=8;
645          switch (todoy)
646          {
647        case 4 :
648        {
649          uchar *addr=xaddr,*daddr=dxaddr;
650          dxaddr=(uchar *)MAP_PUT2((long)daddr,(long)addr,(long)ct,8);
651          xaddr+=8;
652
653          addr+=scr_w; daddr+=scr_w;
654          MAP_PUT2((long)daddr,(long)addr,(long)ct,8);   addr+=scr_w; daddr+=scr_w;
655          MAP_PUT2((long)daddr,(long)addr,(long)ct,8);   addr+=scr_w; daddr+=scr_w;
656          MAP_PUT2((long)daddr,(long)addr,(long)ct,8);
657        } break;
658        case 3 :
659        {
660          uchar *addr=xaddr,*daddr=dxaddr;
661          dxaddr=(uchar *)MAP_PUT2((long)daddr,(long)addr,(long)ct,8);
662          xaddr+=8;
663
664          addr+=scr_w; daddr+=scr_w;
665          MAP_PUT2((long)daddr,(long)addr,(long)ct,8);   addr+=scr_w; daddr+=scr_w;
666          MAP_PUT2((long)daddr,(long)addr,(long)ct,8);
667
668
669        } break;   
670        case 2 :
671        {
672          uchar *addr=xaddr,*daddr=dxaddr;
673          dxaddr=(uchar *)MAP_PUT2((long)daddr,(long)addr,(long)ct,8);
674          xaddr+=8;
675
676          addr+=scr_w; daddr+=scr_w;
677          MAP_PUT2((long)daddr,(long)addr,(long)ct,8);
678
679        } break;
680        case 1 :
681        { dxaddr=(uchar *)MAP_PUT((long)dxaddr,(long)xaddr,(long)ct,8);
682          xaddr+=8;   
683        } break;
684          }
685        } break;
686/*        case 4 :
687        {
688          x+=4;
689          switch (todoy)
690          {
691        case 4 :
692        {
693          uchar *addr=xaddr;
694          xaddr=(uchar *)MAP_PUT(0,(long)addr,(long)ct,4); addr+=scr_w; daddr+=scr_w;
695          MAP_PUT(0,(long)addr,(long)ct,4);                addr+=scr_w; daddr+=scr_w;
696          MAP_PUT(0,(long)addr,(long)ct,4);                addr+=scr_w; daddr+=scr_w;
697          MAP_PUT(0,(long)addr,(long)ct,4);
698        } break;
699        case 3 :
700        {
701          uchar *addr=xaddr;
702          xaddr=(uchar *)MAP_PUT(0,(long)addr,(long)ct,4); addr+=scr_w;  daddr+=scr_w;
703          MAP_PUT(0,(long)addr,(long)ct,4);                addr+=scr_w;  daddr+=scr_w;
704          MAP_PUT(0,(long)addr,(long)ct,4);
705        } break;   
706        case 2 :
707        {
708          uchar *addr=xaddr;
709          xaddr=(uchar *)MAP_PUT(0,(long)addr,(long)ct,4); addr+=scr_w; daddr+=scr_w;
710          MAP_PUT(0,(long)addr,(long)ct,4);
711        } break;
712        case 1 : xaddr=(uchar *)MAP_PUT(0,(long)xaddr,(long)ct,4); break;
713          }
714        } break; */
715        default :
716        {
717          x+=todox;
718          if (todoy==1)
719          {
720            dxaddr=(uchar *)MAP_PUT2((long)dxaddr,(long)xaddr,(long)ct,todox);
721        xaddr+=todox;
722          }
723          else
724          {
725        uchar *addr=xaddr,*daddr=dxaddr;
726        dxaddr=(uchar *)MAP_PUT2((long)dxaddr,(long)xaddr,(long)ct,todox);
727        xaddr+=todox;
728
729        addr+=scr_w;
730        daddr+=scr_w;
731
732        int cc=todoy-1;
733        while (cc--)
734        {
735          MAP_PUT2((long)daddr,(long)addr,(long)ct,todox);
736          addr+=scr_w;
737          daddr+=scr_w;
738        }                 
739          }
740        }
741      }
742    }
743           
744    int yadd=scr_w*todoy;
745    yaddr+=yadd;
746    dyaddr+=yadd;
747
748    y+=todoy;
749      }
750    }
751  }
752  while (first)
753  {
754    light_patch *p=first;
755    first=first->next;
756    delete p;
757  }
758}
759
760
761
762
763void add_light_spec(spec_directory *sd, char *level_name)
764{
765  long size=4+4;  // number of lights and minimum light levels
766  for (light_source *f=first_light_source;f;f=f->next)
767    size+=6*4+1;
768  sd->add(new spec_entry(SPEC_LIGHT_LIST,"lights",NULL,size,0));
769}
770
771void write_lights(jFILE *fp)
772{
773  int t=0;
774  for (light_source *f=first_light_source;f;f=f->next) t++;
775  fp->write_uint32(t);
776  fp->write_uint32(min_light_level);
777  for (f=first_light_source;f;f=f->next)
778  {
779    fp->write_uint32(f->x);
780    fp->write_uint32(f->y);
781    fp->write_uint32(f->xshift);
782    fp->write_uint32(f->yshift);
783    fp->write_uint32(f->inner_radius);
784    fp->write_uint32(f->outer_radius);
785    fp->write_uint8(f->type);
786  }
787}
788
789
790int send_lights(net_descriptor *os)
791{
792  packet pk;
793  int t=0;
794  for (light_source *f=first_light_source;f;f=f->next) t++;
795  pk.write_uint32(t);
796  pk.write_uint16(min_light_level);
797  if (!os->send(pk)) return 0;
798  for (f=first_light_source;f;f=f->next)
799  {
800    pk.reset();
801    pk.write_uint32(f->x);
802    pk.write_uint32(f->y);
803    pk.write_uint32(f->xshift);
804    pk.write_uint32(f->yshift);
805    pk.write_uint32(f->inner_radius);
806    pk.write_uint32(f->outer_radius);
807    pk.write_uint32(f->type);
808    if (!os->send(pk)) return 0;
809  }
810  return 1;
811}
812
813
814void read_lights(spec_directory *sd, jFILE *fp, char const *level_name)
815{
816  delete_all_lights();
817  spec_entry *se=sd->find("lights");
818  if (se)
819  {
820    fp->seek(se->offset,SEEK_SET);
821    long t=fp->read_uint32();
822    min_light_level=fp->read_uint32();
823    light_source *last;
824    while (t)
825    {
826      t--;
827      long x=fp->read_uint32();
828      long y=fp->read_uint32();
829      long xshift=fp->read_uint32();
830      long yshift=fp->read_uint32();
831      long ir=fp->read_uint32();
832      long ora=fp->read_uint32();
833      long ty=fp->read_uint8();
834
835      light_source *p=new light_source(ty,x,y,ir,ora,xshift,yshift,NULL);
836
837      if (first_light_source)
838        last->next=p;
839      else first_light_source=p;
840      last=p;
841    }
842  }
843}
844
845
846int receive_lights(net_descriptor *os)
847{
848  packet pk;
849  if (!os->get(pk)) { printf("net error : light total\n"); return 0; }
850  long t;
851  if (pk.read((uchar *)&t,4)!=4)
852  { printf("net error : (t) packet incomplete\n"); return 0; }
853  t=lltl(t);
854
855  if (pk.read((uchar *)&min_light_level,2)!=2)
856  { printf("net error : (minl) packet incomplete\n"); return 0; }
857  min_light_level=lstl(min_light_level);
858
859  light_source *last;
860  printf("Reading %d lights\n",t);
861  while (t)
862  {
863    if (!os->get(pk)) {printf("net error : read light\n"); return 0; }
864    t--;
865    long dt[7];
866    if (pk.read((uchar *)dt,7*4)!=7*4) return 0;
867
868
869    light_source *p=new light_source(lltl(dt[6]),
870                       lltl(dt[0]),lltl(dt[1]),
871                       lltl(dt[4]),lltl(dt[5]),
872                       lltl(dt[2]),lltl(dt[3]),NULL);
873
874    if (first_light_source)
875      last->next=p;
876    else first_light_source=p;
877      last=p;
878  }
879  return 1;
880}
881
882
883
Note: See TracBrowser for help on using the repository browser.