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

Last change on this file since 56 was 56, checked in by Sam Hocevar, 11 years ago
  • Add licensing terms to most C / C++ files (Ref #5).
File size: 19.9 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 *)jmalloc(256*64,"light table");
188  green_light=(unsigned char *)jmalloc(256*64,"green light");
189  for (int i=0;i<TTINTS;i++)
190      tints[i]=(uchar *)jmalloc(256,"color tint");
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 **)jmalloc(total*sizeof(light_source *),"light patches");
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 **)jrealloc(p->lights,sizeof(light_source *)*p->total,"patch_list");
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 **)jrealloc(p->lights,sizeof(light_source *)*p->total,"patch_list");
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
496#ifdef __WATCOMC__
497extern "C" {
498extern long MAP_PUT(long pad, long screen_addr, long remap, long w);
499extern long MAP_PUT2(long dest, long screen_addr, long remap, long w);
500} ;
501#else
502inline long MAP_PUT(long pad, long screen_addr, long remap, long w)
503{ while (w--)
504  {
505    *((uchar *)(screen_addr))=*((uchar *)remap+*((uchar *)screen_addr));
506    screen_addr++;
507  }
508  return screen_addr;
509}
510
511inline long MAP_PUT2(long dest_addr, long screen_addr, long remap, long w)
512{ while (w--)
513  {
514    *((uchar *)(dest_addr))=*((uchar *)remap+*((uchar *)screen_addr));
515    screen_addr++;
516    dest_addr++;
517  }
518  return dest_addr;
519}
520
521#endif
522
523
524inline long calc_lv(light_patch *lp, long sx, long sy)
525{
526  light_source **lon_p=lp->lights;
527  long lv=min_light_level;
528  int light_on;
529  for (light_on=lp->total-1;light_on>=0;light_on--)
530  {
531    light_source *fn=*lon_p;
532    long *dt=&(*lon_p)->type;
533    if (*dt==9)
534    {
535      lv=fn->inner_radius;
536      light_on=0;           
537    } else
538    {
539      dt++;
540      int dx=abs(*dt-sx); dt++;
541      dx<<=*dt;  dt++;
542
543      int dy=abs(*dt-sy); dt++;
544      dy<<=*dt;  dt++;
545
546      int r2;
547      if (dx<dy)
548      r2=dx+dy-(dx>>1);
549      else r2=dx+dy-(dy>>1);
550     
551      if (r2<*dt)
552      {         
553        int v=*dt-r2; dt++;             
554        lv+=v*(*dt)>>16;
555      }
556    }
557    lon_p++;
558  }
559  if (lv>63) return 63;
560  else return lv;
561
562}
563
564
565void light_screen(image *sc, long screenx, long screeny, uchar *light_lookup)
566{
567  int lx_run,ly_run;
568  switch (light_detail)
569  {
570    case HIGH_DETAIL :
571    { lx_run=2; ly_run=1; } break;
572    case MEDIUM_DETAIL :
573    { lx_run=3; ly_run=2; } break;
574    case LOW_DETAIL :
575    { lx_run=4; ly_run=3; } break;
576    case POOR_DETAIL :                   // low detail lighting alread taken care of.
577    return ;
578  }
579
580  short cx1,cy1,cx2,cy2;
581  sc->get_clip(cx1,cy1,cx2,cy2);
582//  sc->add_dirty(cx1,cy1,cx2,cy2);
583  unsigned char *mint=light_lookup+min_light_level*256;
584  screenx-=cx1;
585  screeny-=cy1;
586
587
588  light_patch *first=make_patch_list(cx1,cy1,cx2,cy2,screenx,screeny);
589
590
591  int ytry=(1<<ly_run),xtry=(1<<lx_run);
592  int calcx_mask=(0xefffffff-(xtry-1));
593  int calcy_mask=(0xefffffff-(ytry-1));
594  int scr_w=screen->width();
595
596  for (light_patch *lp=first;lp;lp=lp->next)
597  {
598    register int x2=lp->x2;
599    if (lp->total==0)  // do dark patches really fast.
600    {
601      unsigned char *sl=screen->scan_line(lp->y1)+lp->x1,*dest;
602#ifdef __WATCOMC__
603      if (get_vmode()==19) dest=(uchar *)0xa0000+lp->y1*320+lp->x1;
604      else dest=sl;
605#else
606      dest=sl;
607#endif
608     
609      int y2=lp->y2;
610      for (int y=lp->y1;y<=y2;y++,sl+=scr_w,dest+=scr_w)
611      {
612        int w=lp->x2-lp->x1+1;
613        MAP_PUT2((long)dest,(long)sl,(long)mint,w);
614      }
615    }
616    else
617    {
618      int todoy;
619      int y2=lp->y2;
620
621      int xmask=(xtry-1);
622      int ymask=(ytry-1);
623
624      uchar *yaddr=screen->scan_line(lp->y1)+lp->x1,*dyaddr;
625#ifdef __WATCOMC__
626      if (get_vmode()==19) dyaddr=((uchar *)0xa0000)+lp->y1*320+lp->x1;
627      else dyaddr=yaddr;
628#else
629      dyaddr=yaddr;
630#endif
631
632      for (int y=lp->y1;y<=y2;)
633      {
634        long sy=(screeny+y);
635        if (y+ytry>lp->y2)        // see how many y lines to do for this block
636          todoy=lp->y2-y+1;
637        else todoy=ytry;
638        int maxy=ytry-(sy&ymask);
639        if (todoy>maxy)
640          todoy=maxy;
641       
642        uchar *xaddr=yaddr,*dxaddr=dyaddr;
643        for (register int x=lp->x1;x<=x2;)
644        {
645          long lv=min_light_level;
646          unsigned char *ct;
647          light_source *f;
648          int todox;
649          if (x+xtry>lp->x2)
650            todox=lp->x2-x+1;
651          else todox=xtry;
652          int sx=(screenx+x);
653          int max=xtry-(sx&xmask);
654          if (todox>max)
655            todox=max;
656
657
658          ct=light_lookup+calc_lv(lp,sx,sy)*256;
659          switch (todox)
660          {
661            case 8 :
662            {
663              x+=8;
664              switch (todoy)
665              {
666                case 4 :
667                {
668                  uchar *addr=xaddr,*daddr=dxaddr;
669                  dxaddr=(uchar *)MAP_PUT2((long)daddr,(long)addr,(long)ct,8);
670                  xaddr+=8;
671
672                  addr+=scr_w; daddr+=scr_w;
673                  MAP_PUT2((long)daddr,(long)addr,(long)ct,8);   addr+=scr_w; daddr+=scr_w;
674                  MAP_PUT2((long)daddr,(long)addr,(long)ct,8);   addr+=scr_w; daddr+=scr_w;
675                  MAP_PUT2((long)daddr,(long)addr,(long)ct,8);
676                } break;
677                case 3 :
678                {
679                  uchar *addr=xaddr,*daddr=dxaddr;
680                  dxaddr=(uchar *)MAP_PUT2((long)daddr,(long)addr,(long)ct,8);
681                  xaddr+=8;
682
683                  addr+=scr_w; daddr+=scr_w;
684                  MAP_PUT2((long)daddr,(long)addr,(long)ct,8);   addr+=scr_w; daddr+=scr_w;
685                  MAP_PUT2((long)daddr,(long)addr,(long)ct,8);
686
687
688                } break;             
689                case 2 :
690                {
691                  uchar *addr=xaddr,*daddr=dxaddr;
692                  dxaddr=(uchar *)MAP_PUT2((long)daddr,(long)addr,(long)ct,8);
693                  xaddr+=8;
694
695                  addr+=scr_w; daddr+=scr_w;
696                  MAP_PUT2((long)daddr,(long)addr,(long)ct,8);
697
698                } break;
699                case 1 :
700                { dxaddr=(uchar *)MAP_PUT((long)dxaddr,(long)xaddr,(long)ct,8);
701                  xaddr+=8;           
702                } break;
703              }
704            } break;
705/*          case 4 :
706            {
707              x+=4;
708              switch (todoy)
709              {
710                case 4 :
711                {
712                  uchar *addr=xaddr;
713                  xaddr=(uchar *)MAP_PUT(0,(long)addr,(long)ct,4); addr+=scr_w; daddr+=scr_w;
714                  MAP_PUT(0,(long)addr,(long)ct,4);                addr+=scr_w; daddr+=scr_w;
715                  MAP_PUT(0,(long)addr,(long)ct,4);                addr+=scr_w; daddr+=scr_w;
716                  MAP_PUT(0,(long)addr,(long)ct,4);
717                } break;
718                case 3 :
719                {
720                  uchar *addr=xaddr;
721                  xaddr=(uchar *)MAP_PUT(0,(long)addr,(long)ct,4); addr+=scr_w;  daddr+=scr_w;
722                  MAP_PUT(0,(long)addr,(long)ct,4);                addr+=scr_w;  daddr+=scr_w;
723                  MAP_PUT(0,(long)addr,(long)ct,4);
724                } break;             
725                case 2 :
726                {
727                  uchar *addr=xaddr;
728                  xaddr=(uchar *)MAP_PUT(0,(long)addr,(long)ct,4); addr+=scr_w; daddr+=scr_w;
729                  MAP_PUT(0,(long)addr,(long)ct,4);
730                } break;
731                case 1 : xaddr=(uchar *)MAP_PUT(0,(long)xaddr,(long)ct,4); break;
732              }
733            } break; */
734            default :
735            {
736              x+=todox;
737              if (todoy==1)
738              {
739                dxaddr=(uchar *)MAP_PUT2((long)dxaddr,(long)xaddr,(long)ct,todox);
740                xaddr+=todox;
741              }
742              else
743              {
744                uchar *addr=xaddr,*daddr=dxaddr;
745                dxaddr=(uchar *)MAP_PUT2((long)dxaddr,(long)xaddr,(long)ct,todox);
746                xaddr+=todox;
747
748                addr+=scr_w;
749                daddr+=scr_w;
750
751                int cc=todoy-1;
752                while (cc--)
753                {
754                  MAP_PUT2((long)daddr,(long)addr,(long)ct,todox);
755                  addr+=scr_w;
756                  daddr+=scr_w;
757                }                               
758              }
759            }
760          }
761        }
762         
763        int yadd=scr_w*todoy;
764        yaddr+=yadd;
765        dyaddr+=yadd;
766
767        y+=todoy;
768      }
769    }
770  }
771  while (first)
772  {
773    light_patch *p=first;
774    first=first->next;
775    delete p;
776  }
777}
778
779
780
781
782void add_light_spec(spec_directory *sd, char *level_name)
783{
784  long size=4+4;  // number of lights and minimum light levels
785  for (light_source *f=first_light_source;f;f=f->next)
786    size+=6*4+1;
787  sd->add(new spec_entry(SPEC_LIGHT_LIST,"lights",NULL,size,0)); 
788}
789
790void write_lights(jFILE *fp)
791{
792  int t=0;
793  for (light_source *f=first_light_source;f;f=f->next) t++;
794  fp->write_uint32(t);
795  fp->write_uint32(min_light_level);
796  for (f=first_light_source;f;f=f->next)
797  {
798    fp->write_uint32(f->x);
799    fp->write_uint32(f->y);
800    fp->write_uint32(f->xshift);
801    fp->write_uint32(f->yshift);
802    fp->write_uint32(f->inner_radius);
803    fp->write_uint32(f->outer_radius);
804    fp->write_uint8(f->type);
805  }
806}
807
808
809int send_lights(net_descriptor *os)
810{
811  packet pk;
812  int t=0;
813  for (light_source *f=first_light_source;f;f=f->next) t++;
814  pk.write_uint32(t);
815  pk.write_uint16(min_light_level);
816  if (!os->send(pk)) return 0;
817  for (f=first_light_source;f;f=f->next)
818  {
819    pk.reset();
820    pk.write_uint32(f->x);
821    pk.write_uint32(f->y);
822    pk.write_uint32(f->xshift);
823    pk.write_uint32(f->yshift);
824    pk.write_uint32(f->inner_radius);
825    pk.write_uint32(f->outer_radius);
826    pk.write_uint32(f->type);
827    if (!os->send(pk)) return 0;   
828  }
829  return 1;
830}
831
832
833void read_lights(spec_directory *sd, jFILE *fp, char const *level_name)
834{
835  delete_all_lights();
836  spec_entry *se=sd->find("lights");
837  if (se)
838  {
839    fp->seek(se->offset,SEEK_SET);
840    long t=fp->read_uint32();
841    min_light_level=fp->read_uint32();
842    light_source *last;
843    while (t)
844    {
845      t--;
846      long x=fp->read_uint32();
847      long y=fp->read_uint32();
848      long xshift=fp->read_uint32();
849      long yshift=fp->read_uint32();
850      long ir=fp->read_uint32();
851      long ora=fp->read_uint32();
852      long ty=fp->read_uint8();
853
854      light_source *p=new light_source(ty,x,y,ir,ora,xshift,yshift,NULL);
855     
856      if (first_light_source)
857        last->next=p;
858      else first_light_source=p;
859      last=p;
860    }
861  }
862}
863
864
865int receive_lights(net_descriptor *os)
866{
867  packet pk;
868  if (!os->get(pk)) { printf("net error : light total\n"); return 0; }
869  long t;
870  if (pk.read((uchar *)&t,4)!=4)
871  { printf("net error : (t) packet incomplete\n"); return 0; }
872  t=lltl(t);
873
874  if (pk.read((uchar *)&min_light_level,2)!=2)
875  { printf("net error : (minl) packet incomplete\n"); return 0; }
876  min_light_level=lstl(min_light_level);
877
878  light_source *last;
879  printf("Reading %d lights\n",t);
880  while (t)
881  {
882    if (!os->get(pk)) {printf("net error : read light\n"); return 0; }
883    t--;
884    long dt[7];
885    if (pk.read((uchar *)dt,7*4)!=7*4) return 0;
886
887
888    light_source *p=new light_source(lltl(dt[6]),
889                                       lltl(dt[0]),lltl(dt[1]),
890                                       lltl(dt[4]),lltl(dt[5]),
891                                       lltl(dt[2]),lltl(dt[3]),NULL);
892     
893    if (first_light_source)
894      last->next=p;
895    else first_light_source=p;
896      last=p;
897  }
898  return 1;
899}
900
901
902
Note: See TracBrowser for help on using the repository browser.