source: abuse/branches/pd/macabuse/src/light.c @ 483

Last change on this file since 483 was 49, checked in by Sam Hocevar, 15 years ago
  • Imported original public domain release, for future reference.
  • Property svn:keywords set to Id
File size: 31.8 KB
Line 
1#include "light.hpp"
2#include <stdlib.h>
3#include "image.hpp"
4#include "macs.hpp"
5#include "video.hpp"
6#include "palette.hpp"
7#include "timing.hpp"
8#include "specs.hpp"
9#include "dprint.hpp"
10#include "filter.hpp"
11#include "status.hpp"
12#include "dev.hpp"
13
14light_source *first_light_source=NULL;
15unsigned char *white_light,*white_light_initial,*green_light,*trans_table;
16short ambient_ramp=0;
17short shutdown_lighting_value,shutdown_lighting=0;
18extern char disable_autolight;   // defined in dev.hpp
19
20#ifdef MAC_PROFILE
21unsigned lighting_loop_time;
22
23extern char kjfie[][256];  // kill me
24int loopnum1,loopnum2,tmp; //kill me
25
26extern long StartTime(int cnt);         //kill me
27extern long DiffTime(char *name, int cnt);   //kill me
28#else
29inline long StartTime(int cnt) { return 0; }         //kill me
30inline long DiffTime(char *name, int cnt) { return 0; }  //kill me
31#endif
32
33int light_detail=MEDIUM_DETAIL;
34
35long light_to_number(light_source *l)
36{
37 
38  if (!l) return 0;
39  int x=1;
40  for (light_source *s=first_light_source;s;s=s->next,x++)
41    if (s==l) return x;
42  return 0;
43}
44
45
46light_source *number_to_light(long x)
47{
48  if (x==0) return NULL;
49  x--;
50  light_source *s=first_light_source;
51  for (;x && s;x--,s=s->next);
52  return s;       
53}
54
55light_source *light_source::copy()
56{
57  next=new light_source(type,x,y,inner_radius,outer_radius,xshift,yshift,next);
58  return next;
59}
60
61void delete_all_lights()
62{
63  while (first_light_source)
64  {
65    if (dev_cont)
66      dev_cont->notify_deleted_light(first_light_source);
67
68    light_source *p=first_light_source;
69    first_light_source=first_light_source->next;
70    delete p;
71  }
72}
73
74void delete_light(light_source *which)
75{
76  if (dev_cont)
77    dev_cont->notify_deleted_light(which);
78
79  if (which==first_light_source)
80  {
81    first_light_source=first_light_source->next;
82    delete which;
83  }
84  else
85  {
86    light_source *f=first_light_source;
87    for (;f->next!=which && f;f=f->next);
88    if (f)
89    {
90      f->next=which->next;
91      delete which;
92    }
93  }
94}
95
96void light_source::calc_range()
97{
98  switch (type)
99  {
100    case 0 :
101    { x1=x-(outer_radius>>xshift); y1=y-(outer_radius>>yshift);
102      x2=x+(outer_radius>>xshift); y2=y+(outer_radius>>yshift);
103    } break;
104    case 1 :
105    { x1=x-(outer_radius>>xshift); y1=y-(outer_radius>>yshift);
106      x2=x+(outer_radius>>xshift); y2=y;
107    } break;
108    case 2 :
109    { x1=x-(outer_radius>>xshift); y1=y;
110      x2=x+(outer_radius>>xshift); y2=y+(outer_radius>>yshift);
111    } break;
112    case 3 :
113    { x1=x; y1=y-(outer_radius>>yshift);
114      x2=x+(outer_radius>>xshift); y2=y+(outer_radius>>yshift);
115    } break;
116    case 4 :
117    { x1=x-(outer_radius>>xshift); y1=y-(outer_radius>>yshift);
118      x2=x; y2=y+(outer_radius>>yshift);
119    } break;
120
121
122    case 5 :
123    { x1=x; y1=y-(outer_radius>>yshift);
124      x2=x+(outer_radius>>xshift); y2=y;
125    } break;
126    case 6 :
127    { x1=x-(outer_radius>>xshift); y1=y-(outer_radius>>yshift);
128      x2=x; y2=y;
129    } break;
130    case 7 :
131    { x1=x-(outer_radius>>xshift); y1=y;
132      x2=x; y2=y+(outer_radius>>yshift);
133    } break;
134    case 8 :
135    { x1=x; y1=y;
136      x2=x+(outer_radius>>xshift); y2=y+(outer_radius>>yshift);
137    } break;
138    case 9 :
139    {
140      x1=x;
141      y1=y;
142      x2=x+xshift;
143      y2=y+yshift;
144    } break;
145
146  }
147  mul_div=(1<<16)/(outer_radius-inner_radius)*64;
148}
149
150light_source::light_source(char Type, long X, long Y, long Inner_radius,
151                           long Outer_radius, long Xshift,  long Yshift, light_source *Next)
152{
153  type=Type;
154  x=X; y=Y;
155  inner_radius=Inner_radius; 
156  outer_radius=Outer_radius;
157  next=Next;
158  known=0;
159  xshift=Xshift;
160  yshift=Yshift;
161  calc_range();
162}
163
164
165int count_lights()
166{
167  int t=0;
168  for (light_source *s=first_light_source;s;s=s->next)
169    t++;
170  return t;
171}
172
173light_source *add_light_source(char type, long x, long y,
174                               long inner, long outer, long xshift, long yshift)
175{
176  first_light_source=new light_source(type,x,y,inner,outer,xshift,yshift,first_light_source);
177  return first_light_source;
178}
179
180
181#define TTINTS 9
182uchar *tints[TTINTS];
183uchar bright_tint[256];
184
185void calc_tint(uchar *tint, int rs, int gs, int bs, int ra, int ga, int ba, palette *pal)
186{
187  palette npal;
188  memset(npal.addr(),0,256);
189  int i=0;
190  for (;i<256;i++)
191  {
192    npal.set(i,(int)rs,(int)gs,(int)bs);
193    rs+=ra; if (rs>255) rs=255; if (rs<0) rs=0;
194    gs+=ga; if (gs>255) gs=255; if (gs<0) gs=0;
195    bs+=ba; if (bs>255) bs=255; if (bs<0) bs=0;
196  }
197  filter f(pal,&npal);
198  filter f2(&npal,pal);
199
200  for (i=0;i<256;i++,tint++)
201    *tint=f2.get_mapping(f.get_mapping(i));
202}
203
204
205void calc_light_table(palette *pal)
206{
207 
208  white_light_initial=(unsigned char *)jmalloc(256*64+256,"light table");
209 
210  // align memory to 256 byte boundary
211  white_light= (unsigned char*)((((unsigned long)white_light_initial) + 255)&~0xff);
212
213//  green_light=(unsigned char *)jmalloc(256*64,"green light");
214  int i=0;
215  for (;i<TTINTS;i++)
216      tints[i]=(uchar *)jmalloc(256,"color tint");
217
218  bFILE *fp=open_file("light.tbl","rb");
219  int recalc=0;
220  if (fp->open_failure())
221  {
222    recalc=1;
223    delete fp;
224  }
225  else
226  {
227    if (fp->read_short()!=calc_crc((unsigned char *)pal->addr(),768))
228      recalc=1;
229    else
230    {
231      fp->read(white_light,256*64);
232//      fp->read(green_light,256*64);
233      for (i=0;i<TTINTS;i++)
234        fp->read(tints[i],256);
235      fp->read(bright_tint,256);
236//      trans_table=(uchar *)jmalloc(256*256,"transparency table");
237//      fp.read(trans_table,256*256);
238    }
239    delete fp;
240  }
241
242  if (recalc)
243  { 
244    dprintf("Palette has changed, recalculating light table...\n");
245    stat_man->push("white light",NULL);
246    int color=0;
247    for (;color<256;color++)
248    {
249      unsigned char r,g,b;
250      pal->get(color,r,g,b);
251      stat_man->update(color*100/256);
252      for (int intensity=63;intensity>=0;intensity--)
253      {
254        if (r>0 || g>0 || b>0)
255          white_light[intensity*256+color]=pal->find_closest(r,g,b);
256        else
257          white_light[intensity*256+color]=0;
258        if (r) r--;  if (g) g--;  if (b) b--;   
259      }
260
261
262
263    }
264    stat_man->pop();
265
266/*    stat_man->push("green light",NULL);
267    for (color=0;color<256;color++)
268    {
269      stat_man->update(color*100/256);
270      unsigned char r,g,b;
271      pal->get(color,b,r,g);
272      r=r*3/5; b=b*3/5; g+=7; if (g>255) g=255;
273
274      for (int intensity=63;intensity>=0;intensity--)
275      {
276        if (r>0 || g>0 || b>0)
277          green_light[intensity*256+color]=pal->find_closest(r,g,b);
278        else
279          green_light[intensity*256+color]=0;
280        if (r) r--; 
281        if ((intensity&1)==1)
282          if (g) g--; 
283        if (b) b--;
284      }
285    }
286    stat_man->pop(); */
287
288    stat_man->push("tints",NULL);
289    uchar t[TTINTS*6]={0,0,0,0,0,0, // normal
290                   0,0,0,1,0,0,     // red
291                   0,0,0,1,1,0,     // yellow
292                   0,0,0,1,0,1,     // purple
293                   0,0,0,1,1,1,     // gray
294                   0,0,0,0,1,0,     // green
295                   0,0,0,0,0,1,     // blue
296                   0,0,0,0,1,1,     // cyan
297
298
299
300
301
302
303                   0,0,0,0,0,0   // reverse green  (night vision effect)
304                 } ;
305    uchar *ti=t+6;
306    uchar *c;
307    for (i=0,c=tints[0];i<256;i++,c++) *c=i;  // make the normal tint (maps everthing to itself)
308    for (i=0,c=tints[TTINTS-1];i<256;i++,c++)  // reverse green
309    {
310      int r=pal->red(i)/2,g=255-pal->green(i)-30,b=pal->blue(i)*3/5+50;
311      if (g<0) g=0;
312      if (b>255) b=0;
313      *c=pal->find_closest(r,g,b);
314    }
315    for (i=0;i<256;i++)
316    {
317      int r=pal->red(i)+(255-pal->red(i))/2,
318          g=pal->green(i)+(255-pal->green(i))/2,
319          b=pal->blue(i)+(255-pal->blue(i))/2;
320      bright_tint[i]=pal->find_closest(r,g,b);
321    }
322
323    // make the colored tints
324    for (i=1;i<TTINTS-1;i++)
325    {
326      stat_man->update(i*100/(TTINTS-1));
327      calc_tint(tints[i],ti[0],ti[1],ti[2],ti[3],ti[4],ti[5],pal);
328      ti+=6;
329    }
330    stat_man->pop();
331/*    dprintf("calculating transparency tables (256 total)\n");
332    trans_table=(uchar *)jmalloc(256*256,"transparency table");
333
334    uchar *tp=trans_table;
335    for (i=0;i<256;i++)
336    {     
337      uchar r1,g1,b1,r2,g2,b2;
338      pal->get(i,r1,g1,b1);
339      if ((i%16)==0)
340        dprintf("%d ",i);
341      for (int j=0;j<256;j++,tp++)
342      {
343        if (r1==0 && r2==0 && b2==0)
344          *tp=j;
345        else
346        {
347          pal->get(j,r2,g2,b2);       
348          *tp=pal->find_closest((r2-r1)*3/7+r1,(g2-g1)*3/7+g1,(b2-b1)*3/7+b1);
349        }
350      }
351    }*/
352
353
354    bFILE *f=open_file("light.tbl","wb");
355    if (f->open_failure())   
356      dprintf("Unable to open file light.tbl for writing\n");
357    else
358    {
359      f->write_short(calc_crc((unsigned char *)pal->addr(),768));
360      f->write(white_light,256*64);
361//      f->write(green_light,256*64);
362      for (int i=0;i<TTINTS;i++)
363        f->write(tints[i],256);
364      fp->write(bright_tint,256);
365//    f.write(trans_table,256*256);
366    }
367    delete f;
368  }
369}
370
371
372light_patch *light_patch::copy(light_patch *Next)
373{
374  light_patch *p=new light_patch(x1,y1,x2,y2,Next);
375  p->total=total;
376  if (total)   
377  {
378    p->lights=(light_source **)jmalloc(total*sizeof(light_source *),"light patches");
379    memcpy(p->lights,lights,total*(sizeof(light_source *)));
380  }
381  else
382    p->lights=NULL;
383  return p;
384}
385
386#define MAX_LP 6
387
388// insert light into list make sure the are sorted by y1
389void insert_light(light_patch *&first, light_patch *l)
390{
391  if (!first)
392    first=l;
393  else if (l->y1<first->y1)
394  {
395    l->next=first;
396    first=l;
397  } else
398  {
399    light_patch *p=first;
400    for (;p->next && p->next->y1<l->y1;p=p->next);
401    l->next=p->next;
402    p->next=l;
403  }
404}
405
406void add_light(light_patch *&first, long x1, long y1, long x2, long y2,
407                            light_source *who)
408
409  light_patch *last=NULL,*next;
410  light_patch *p=first;
411  for (;p;p=next)
412  {
413    next=p->next;
414    // first see if light patch we are adding is enclosed entirely by another patch
415    if (x1>=p->x1 && y1>=p->y1 && x2<=p->x2 && y2<=p->y2)
416    {
417      if (p->total==MAX_LP) return ;
418
419      if (x1>p->x1)
420      {
421        light_patch *l=p->copy(NULL);
422        l->x2=x1-1;
423        insert_light(first,l);
424      }
425      if (x2<p->x2)
426      {
427        light_patch *l=p->copy(NULL);
428        l->x1=x2+1;
429        insert_light(first,l);
430      }
431      if (y1>p->y1)
432      {
433        light_patch *l=p->copy(NULL);
434        l->x1=x1;
435        l->x2=x2;
436        l->y2=y1-1;
437        insert_light(first,l);
438      }
439      if (y2<p->y2)
440      {
441        light_patch *l=p->copy(NULL);
442        l->x1=x1;
443        l->x2=x2;
444        l->y1=y2+1;
445        insert_light(first,l);
446      }
447      p->x1=x1; p->y1=y1; p->x2=x2; p->y2=y2;
448      // p has possibly changed it's y1, so we need to move it to it's correct sorted
449      // spot in the list
450      if (first==p)
451        first=first->next;
452      else
453      {
454        light_patch *q=first;
455        for (;q->next!=p;q=q->next);
456        q->next=p->next;
457      }
458      insert_light(first,p);
459     
460
461      p->total++;     
462      p->lights=(light_source **)jrealloc(p->lights,sizeof(light_source *)*p->total,"patch_list");
463      p->lights[p->total-1]=who;
464      return ;
465    }
466
467    // see if the patch completly covers another patch.
468    if (x1<=p->x1 && y1<=p->y1 && x2>=p->x2 && y2>=p->y2)
469    {
470      if (x1<p->x1)
471        add_light(first,x1,y1,p->x1-1,y2,who);
472      if (x2>p->x2)
473        add_light(first,p->x2+1,y1,x2,y2,who);
474      if (y1<p->y1)
475        add_light(first,p->x1,y1,p->x2,p->y1-1,who);
476      if (y2>p->y2)
477        add_light(first,p->x1,p->y2+1,p->x2,y2,who);
478      if (p->total==MAX_LP)  return ;
479      p->total++;     
480      p->lights=(light_source **)jrealloc(p->lights,sizeof(light_source *)*p->total,"patch_list");
481      p->lights[p->total-1]=who;
482      return ;
483    }
484
485    // see if we intersect another rect
486    if (!(x2<p->x1 || y2<p->y1 || x1>p->x2 || y1>p->y2)) 
487    {
488      int ax1,ay1,ax2,ay2;
489      if (x1<p->x1)
490      {
491        add_light(first,x1,max(y1,p->y1),p->x1-1,min(y2,p->y2),who);
492        ax1=p->x1;
493      } else
494        ax1=x1;
495
496      if (x2>p->x2)
497      {
498        add_light(first,p->x2+1,max(y1,p->y1),x2,min(y2,p->y2),who);
499        ax2=p->x2;
500      }
501      else
502        ax2=x2;
503
504      if (y1<p->y1)
505      {       
506        add_light(first,x1,y1,x2,p->y1-1,who);
507        ay1=p->y1;
508      } else
509        ay1=y1;
510
511      if (y2>p->y2)
512      {
513        add_light(first,x1,p->y2+1,x2,y2,who);
514        ay2=p->y2;
515      } else
516        ay2=y2;
517
518       
519      add_light(first,ax1,ay1,ax2,ay2,who);     
520
521      return ;   
522    }
523  }
524}
525 
526light_patch *find_patch(int screenx, int screeny, light_patch *list)
527{
528  for (;list;list=list->next)
529  {
530    if (screenx>=list->x1 && screenx<=list->x2 && screeny>=list->y1 && screeny<=list->y2)
531      return list;
532  }
533  return NULL;
534}
535
536/* shit
537int calc_light_value(light_patch *which, long x, long y)
538{
539  int lv=0;
540  int t=which->total;
541  for (register int i=t-1;i>=0;i--)
542  {   
543    light_source *fn=which->lights[i];
544    if (fn->type==9)
545    {
546      lv=fn->inner_radius;
547      i=0;
548    }
549    else
550    {
551      long dx=abs(fn->x-x)<<fn->xshift;
552      long dy=abs(fn->y-y)<<fn->yshift;
553      long  r2;
554      if (dx<dy)
555        r2=dx+dy-(dx>>1);
556      else r2=dx+dy-(dy>>1);
557   
558      if (r2>=fn->inner_radius)
559      {
560        if (r2<fn->outer_radius)
561        {
562          lv+=((fn->outer_radius-r2)*fn->mul_div)>>16;
563        }
564      } else lv=63;       
565    }
566  }
567  if (lv>63) return 63;
568  else
569    return lv;
570} */
571
572
573void reduce_patches(light_patch *f)   // find constant valued patches
574{
575 
576}
577
578light_patch *make_patch_list(int width, int height, long screenx, long screeny)
579{
580  light_patch *first=new light_patch(0,0,width-1,height-1,NULL);
581
582  for (light_source *f=first_light_source;f;f=f->next)   // determine which lights will have effect
583  {
584    long x1=f->x1-screenx,y1=f->y1-screeny,
585        x2=f->x2-screenx,y2=f->y2-screeny;
586    if (x1<0) x1=0;
587    if (y1<0) y1=0;
588    if (x2>=width)  x2=width-1;
589    if (y2>=height) y2=height-1;
590
591    if (x1<=x2 && y1<=y2)
592      add_light(first,x1,y1,x2,y2,f);
593  }
594  reduce_patches(first);
595
596  return first;
597}
598
599
600void delete_patch_list(light_patch *first)
601{
602  while (first)
603  {
604    light_patch *p=first;
605    first=first->next;
606    delete p;
607  }
608}
609
610/*
611#ifdef __WATCOMC__
612extern "C" {
613extern long MAP_PUT(long pad, long screen_addr, long remap, long w);
614} ;
615#else*/
616
617inline void MAP_PUT(long screen_addr, long remap, long w)
618{
619  register int cx=w;
620  register int di=screen_addr;
621  register int si=remap;
622  while (cx--)
623    *((uchar *)(di++))=*((uchar *)si+*((uchar *)di));
624}
625
626inline void MAP_2PUT(long in_addr, long out_addr, long remap, long w)
627{
628  while (w--)
629  {
630    uchar x=*(((uchar *)remap)+(*(uchar *)(in_addr++)));
631    *((uchar *)(out_addr++))=x;
632    *((uchar *)(out_addr++))=x;
633  }
634}
635
636/*
637#endif
638
639inline void PUT8(long *addr, uchar *remap)
640{
641  register ulong in_pixels;
642  register ulong pixel;
643  register ulong out_pixels;
644  in_pixels=*addr;
645  pixel=in_pixels;
646  out_pixels=remap[(uchar)pixel];
647 
648  pixel=in_pixels;
649  pixel>>=8;
650  pixel=remap[(uchar)pixel];
651  pixel<<=8;
652  out_pixels|=pixel;
653
654  pixel=in_pixels;
655  pixel>>=16;
656  pixel=remap[(uchar)pixel];
657  pixel<<=16;
658  out_pixels|=pixel;
659
660  pixel=in_pixels;
661  pixel>>=24;
662  pixel=remap[(uchar)pixel];
663  pixel<<=24;
664  out_pixels|=pixel;
665
666  *addr=out_pixels;        // send out bus
667
668  // do next 4
669  in_pixels=addr[1];
670
671  pixel=in_pixels;
672  pixel&=0xff;
673  out_pixels=remap[pixel];
674 
675  pixel=in_pixels;
676  pixel>>=8;
677  pixel=remap[(uchar)pixel];
678  pixel<<=8;
679  out_pixels|=pixel;
680
681  pixel=in_pixels;
682  pixel>>=16;
683  pixel=remap[(uchar)pixel];
684  pixel<<=16;
685  out_pixels|=pixel;
686
687  pixel=in_pixels;
688  pixel>>=24;
689  pixel=remap[(uchar)pixel];
690  pixel<<=24;
691  out_pixels|=pixel; 
692  addr[1]=out_pixels;        // send out bus
693 
694}
695
696inline long MAP_PUT2(long dest_addr, long screen_addr, long remap, long w)
697{ while (w--)
698  {
699    *((uchar *)(dest_addr))=*((uchar *)remap+*((uchar *)screen_addr));
700    screen_addr++;
701    dest_addr++;
702  }
703  return dest_addr;
704}
705
706*/
707
708ushort min_light_level;
709// calculate the light value for this block.  sum up all contritors
710inline int calc_light_value(light_patch *lp,   // light patch to look at
711                            long sx,           // screen x & y
712                            long sy)
713{
714  int lv=min_light_level,r2,light_count;
715  register int dx,dy;           // x and y distances
716
717  light_source **lon_p=lp->lights;
718
719  for (light_count=lp->total;light_count>0;light_count--)
720  {
721    light_source *fn=*lon_p;
722    register long *dt=&(*lon_p)->type;
723                                     // note we are accessing structure members by bypassing the compiler
724                                     // for speed, this may not work on all compilers, but don't
725                                     // see why it shouldn't..  all members are long
726   
727    if (*dt==9)                      // (dt==type),  if light is a Solid rectangle, return it value
728      return fn->inner_radius;
729    else
730    {
731      dt++;
732      dx=abs(*dt-sx); dt++;               // xdist between light and this block  (dt==x)
733      dx<<=*dt;  dt++;                    // shift makes distance further,
734                                          // making light skinner. (dt==xshift)
735
736      dy=abs(*dt-sy); dt++;                   // ydist (dt==y)
737      dy<<=*dt;  dt++;                        // (dt==yshift)
738
739      if (dx<dy)                     // calculate approximate distance
740        r2=dx+dy-(dx>>1);
741      else r2=dx+dy-(dy>>1);
742     
743      if (r2<*dt)                    // if this withing the light's outer radius?  (dt==outer_radius)
744      {         
745        int v=*dt-r2; dt++;             
746        lv+=v*(*dt)>>16;
747      }
748    }
749    lon_p++;
750  }
751
752  if (lv>63)
753    return 63;          // lighting table only has 64 (256 bytes) entries
754  else return lv;
755}
756
757
758/*#ifdef __WATCOMC__
759
760extern "C" void remap_line_asm(uchar *screen_line,uchar *light_lookup,uchar *remap_line,int count);
761
762#else */
763
764#if 0
765//defined( __MAC__ ) && defined( __POWERPC__ )
766asm void remap_line_asm2(uchar *addr,uchar *light_lookup,uchar *remap_line,int count)
767//inline void remap_line_asm2(uchar *addr,uchar *light_lookup,uchar *remap_line,int count)
768{
769        stmw            r17, -60(SP)
770        // r3 = addr
771        // r4 = light_lookup
772        // r5 = remap_line
773        // r6 = count
774        addic           r5, r5, -1                                              // remap_line--
775        lwz                     r18, 0(r3)
776        lwzu            r17, 4(r3)
777        addic.  r6, r6, 0
778        b                               remap_end_loop
779       
780remap_loop:
781        mr                      r30, r4
782        lbzu            r31, 1(r5)                                              // remap_line++ ; r31 = *remap_line
783        rlwimi  r31, r31, 8, 0, 31              // r31 = *remap_line << 8
784        add                     r30, r30, r31                                   // r30 = light_lookup + (*remap_line << 8)
785        mr                      r23, r30
786
787        mr                      r29, r18
788        mr                      r28, r17
789       
790        lwzu            r18, 4(r3)                                              // addr+=4 ; r29 = *(long*)addr
791        lwzu            r17, 4(r3)                                              // addr+=4 ; r28 = *(long*)addr
792
793        rlwimi  r30, r29, 0, 24, 31             // r30 = light_lookup + (*remap_line << 8) + addr[3]
794        rlwimi  r23, r28, 0, 24, 31             // r23 = light_lookup + (*remap_line << 8) + addr[7]
795        lbz                     r27, 0(r30)                                             // r27 = (r30)
796        lbz                     r22, 0(r23)                                             // r22 = (r23)
797        rlwimi  r30, r29, 8, 24, 31             // r30 = light_lookup + (*remap_line << 8) + addr[0]
798        rlwimi  r23, r28, 8, 24, 31             // r23 = light_lookup + (*remap_line << 8) + addr[4]
799        lbz                     r26, 0(r30)                                             // r26 = (r30)
800        lbz                     r21, 0(r23)                                             // r21 = (r23)
801        rlwimi  r30, r29, 16, 24, 31    // r30 = light_lookup + (*remap_line << 8) + addr[1]
802        rlwimi  r23, r28, 16, 24, 31    // r23 = light_lookup + (*remap_line << 8) + addr[5]
803        rlwimi  r27, r26, 24, 0, 7
804        rlwimi  r22, r21, 24, 0, 7
805        lbz                     r25, 0(r30)                                             // r25 = (r30)
806        lbz                     r20, 0(r23)                                             // r20 = (r23)
807        rlwimi  r30, r29, 24, 24, 31    // r30 = light_lookup + (*remap_line << 8) + addr[2]
808        rlwimi  r23, r28, 24, 24, 31    // r23 = light_lookup + (*remap_line << 8) + addr[6]
809        rlwimi  r27, r25, 16, 8, 15
810        rlwimi  r22, r20, 16, 8, 15
811        lbz                     r24, 0(r30)                                             // r24 = (r30)
812        lbz                     r19, 0(r23)                                             // r19 = (r23)
813        rlwimi  r27, r24, 8, 16, 23
814        rlwimi  r22, r19, 8, 16, 23
815
816        stw                     r27, -12(r3)
817        stw                     r22, -8(r3)
818
819        addic.  r6, r6, -1
820remap_end_loop:
821        bgt                     remap_loop
822        nop
823
824        lmw                     r17, -60(SP)
825        blr
826       
827}
828#else
829void remap_line_asm2(uchar *addr,uchar *light_lookup,uchar *remap_line,int count)
830//inline void remap_line_asm2(uchar *addr,uchar *light_lookup,uchar *remap_line,int count)
831{
832  while (count--)
833  {
834    uchar *off=light_lookup+(((long)*remap_line)<<8);
835    remap_line++;
836
837    *addr=off[*addr];
838    addr[1]=off[addr[1]];
839    addr[2]=off[addr[2]];
840    addr[3]=off[addr[3]];
841    addr[4]=off[addr[4]];
842    addr[5]=off[addr[5]];
843    addr[6]=off[addr[6]];
844    addr[7]=off[addr[7]];
845    addr+=8;
846
847  }
848}
849#endif
850
851//#endif
852
853
854inline void put_8line(uchar *in_line, uchar *out_line, uchar *remap, uchar *light_lookup, int count)
855{
856  uchar v;
857  int x;
858  for (x=0;x<count;x++)                       
859  {                                           
860    uchar *off=light_lookup+(((long)*remap)<<8);
861
862    v=off[*(in_line++)];
863    *(out_line++)=v;
864    *(out_line++)=v;
865
866    v=off[*(in_line++)];
867    *(out_line++)=v;
868    *(out_line++)=v;
869
870    v=off[*(in_line++)];
871    *(out_line++)=v;
872    *(out_line++)=v;
873
874    v=off[*(in_line++)];
875    *(out_line++)=v;
876    *(out_line++)=v;
877
878    v=off[*(in_line++)];
879    *(out_line++)=v;
880    *(out_line++)=v;
881
882    v=off[*(in_line++)];
883    *(out_line++)=v;
884    *(out_line++)=v;
885
886    v=off[*(in_line++)];
887    *(out_line++)=v;
888    *(out_line++)=v;
889
890    v=off[*(in_line++)];
891    *(out_line++)=v;
892    *(out_line++)=v;
893
894    remap++;
895  }
896}
897
898
899void light_screen(image *sc, long screenx, long screeny, uchar *light_lookup, ushort ambient)
900{
901  int lx_run,ly_run;                     // light block x & y run size in pixels ==  (1<<lx_run)
902
903#if defined( __MAC__ ) && !defined( __POWERPC__ )
904        return;
905#endif
906
907        StartTime(14); //kill me
908  if (shutdown_lighting && !disable_autolight)
909    ambient=shutdown_lighting_value;
910
911  switch (light_detail)
912  {
913    case HIGH_DETAIL :
914    { lx_run=2; ly_run=1; } break;       // 4 x 2 patches
915    case MEDIUM_DETAIL :
916    { lx_run=3; ly_run=2; } break;       // 8 x 4 patches  (default)
917    case LOW_DETAIL :
918    { lx_run=4; ly_run=3; } break;       // 16 x 8 patches
919    case POOR_DETAIL :                   // poor detail is no lighting
920    return ;
921  }
922  if ((int)ambient+ambient_ramp<0)
923    min_light_level=0;
924  else if ((int)ambient+ambient_ramp>63)
925    min_light_level=63;
926  else min_light_level=(int)ambient+ambient_ramp;
927
928  if (ambient==63) return ;
929  short cx1,cy1,cx2,cy2;
930  sc->get_clip(cx1,cy1,cx2,cy2);
931
932  unsigned char *mint=light_lookup+min_light_level*256;
933
934  light_patch *first=make_patch_list(cx2-cx1+1,cy2-cy1+1,screenx,screeny);
935
936
937  int ytry=(1<<ly_run),xtry=(1<<lx_run);
938  int calcx_mask=(0xefffffff-(xtry-1));
939  int calcy_mask=(0xefffffff-(ytry-1));
940  int scr_w=screen->width();
941
942
943  int prefix_x=(screenx&7);
944  int prefix=screenx&7;
945  if (prefix)
946    prefix=8-prefix;
947  int suffix_x=cx2-cx1-(screenx&7);
948
949  int inside_xoff=(screenx+7)&(~7);
950
951  int suffix=(cx2-cx1-prefix+1)&7;
952
953
954  long remap_size=((cx2-cx1+1-prefix-suffix)>>lx_run);
955
956  uchar *remap_line=(uchar *)jmalloc(remap_size,"light remap line");
957
958  light_patch *f=first;
959  uchar *screen_line=screen->scan_line(cy1)+cx1;
960
961//      lighting_loop_time=0;
962
963//      DiffTime("        PreLite",14); //kill me
964       
965//      loopnum1 = 0; // kill me
966        StartTime(15); //kill me
967  for (int y=cy1;y<=cy2;)
968  {
969//              loopnum1++; // kill me
970    int x,count;
971    uchar *rem=remap_line;
972
973    int todoy=4-((screeny+y)&3);
974    if (y+todoy>cy2)
975      todoy=cy2-y+1;
976
977    int calcy=((y+screeny)&(~3))-cy1;
978   
979//              StartTime(12);
980    if (suffix)
981    {
982      light_patch *lp=f;
983      for (;(lp->y1>y-cy1 || lp->y2<y-cy1 ||
984                              lp->x1>suffix_x || lp->x2<suffix_x);lp=lp->next);
985      long caddr=(long)screen_line+cx2-cx1+1-suffix;
986      uchar *r=light_lookup+(((long)calc_light_value(lp,suffix_x+screenx,calcy)<<8));
987      switch (todoy)
988      {
989                                case 4 :
990                                {
991                                  MAP_PUT(caddr,(long)r,suffix); caddr+=scr_w;
992                                }
993                                case 3 :
994                                { MAP_PUT(caddr,(long)r,suffix); caddr+=scr_w;}
995                                case 2 :
996                                { MAP_PUT(caddr,(long)r,suffix); caddr+=scr_w;}
997                                case 1 :
998                                {
999                                  MAP_PUT(caddr,(long)r,suffix);
1000                                }
1001      }
1002    }
1003
1004    if (prefix)
1005    {
1006      light_patch *lp=f;
1007      for (;(lp->y1>y-cy1 || lp->y2<y-cy1 ||
1008                              lp->x1>prefix_x || lp->x2<prefix_x);lp=lp->next);
1009
1010      uchar *r=light_lookup+(((long)calc_light_value(lp,prefix_x+screenx,calcy)<<8));
1011      long caddr=(long)screen_line;
1012      switch (todoy)
1013      {
1014                                case 4 :
1015                                {
1016                                  MAP_PUT(caddr,(long)r,prefix);
1017                                  caddr+=scr_w;
1018                                }
1019                                case 3 :
1020                                { MAP_PUT(caddr,(long)r,prefix); caddr+=scr_w; }
1021                                case 2 :
1022                                { MAP_PUT(caddr,(long)r,prefix); caddr+=scr_w; }
1023                                case 1 :
1024                                { MAP_PUT(caddr,(long)r,prefix); }
1025      }
1026      screen_line+=prefix;
1027    }
1028//              DiffTime("          MAPPUT",16);
1029
1030 
1031//              loopnum2 = 0; // kill me
1032//              StartTime(17); // kill me
1033    for (x=prefix,count=0;count<remap_size;count++,x+=8,rem++)   
1034    {
1035//      loopnum2++; //kill me
1036      light_patch *lp=f;
1037      for (;(lp->y1>y-cy1 || lp->y2<y-cy1 || lp->x1>x || lp->x2<x);lp=lp->next);
1038      *rem=calc_light_value(lp,x+screenx,calcy);
1039    }
1040    uchar *addr,*oaddr;
1041//              sprintf(kjfie[17],"          Calc   %8d = %2d(%4d)",tmp = DiffTime("",17),loopnum2, tmp/loopnum2);// kill me
1042
1043//              StartTime(18); //kill me
1044    switch (todoy)
1045    {
1046      case 4 :   
1047      remap_line_asm2(screen_line,light_lookup,remap_line,count);  y++; todoy--;  screen_line+=scr_w;
1048      case 3 :
1049      remap_line_asm2(screen_line,light_lookup,remap_line,count);  y++; todoy--;  screen_line+=scr_w;
1050      case 2 :
1051      remap_line_asm2(screen_line,light_lookup,remap_line,count);  y++; todoy--;  screen_line+=scr_w;
1052      case 1 :
1053      remap_line_asm2(screen_line,light_lookup,remap_line,count);  y++; todoy--;  screen_line+=scr_w;
1054    }
1055//              DiffTime("          Remap",18); // kill me
1056               
1057    screen_line-=prefix;
1058
1059  }
1060  //    sprintf(kjfie[15],"        Lite     %8d = %2d(%4d)",tmp = DiffTime("",15),loopnum1,tmp/loopnum1);// kill me
1061
1062
1063  while (first)
1064  {
1065    light_patch *p=first;
1066    first=first->next;
1067    delete p;
1068  }
1069  jfree(remap_line);
1070}
1071
1072
1073void double_light_screen(image *sc, long screenx, long screeny, uchar *light_lookup, ushort ambient,
1074                         image *out, long out_x, long out_y)
1075{
1076  if (sc->width()*2+out_x>out->width() ||
1077      sc->height()*2+out_y>out->height())
1078    return ;   // screen was resized and small_render has not changed size yet
1079
1080
1081  int lx_run,ly_run;                     // light block x & y run size in pixels ==  (1<<lx_run)
1082  switch (light_detail)
1083  {
1084    case HIGH_DETAIL :
1085    { lx_run=2; ly_run=1; } break;       // 4 x 2 patches
1086    case MEDIUM_DETAIL :
1087    { lx_run=3; ly_run=2; } break;       // 8 x 4 patches  (default)
1088    case LOW_DETAIL :
1089    { lx_run=4; ly_run=3; } break;       // 16 x 8 patches
1090    case POOR_DETAIL :                   // poor detail is no lighting
1091    return ;
1092  }
1093  if ((int)ambient+ambient_ramp<0)
1094    min_light_level=0;
1095  else if ((int)ambient+ambient_ramp>63)
1096    min_light_level=63;
1097  else min_light_level=(int)ambient+ambient_ramp;
1098
1099  short cx1,cy1,cx2,cy2;
1100  sc->get_clip(cx1,cy1,cx2,cy2);
1101
1102
1103  if (ambient==63)      // lights off, just double the pixels
1104  {
1105    uchar *src=sc->scan_line(0);
1106    uchar *dst=out->scan_line(out_y+cy1*2)+cx1*2+out_x;
1107    int d_skip=out->width()-sc->width()*2;
1108    int x,y;
1109    ushort v;
1110    for (y=sc->height();y;y--)
1111    {
1112      for (x=sc->width();x;x--)
1113      {
1114        v=*(src++);
1115        *(dst++)=v;
1116        *(dst++)=v;
1117      }
1118      dst=dst+d_skip;
1119      memcpy(dst,dst-out->width(),sc->width()*2);
1120      dst+=out->width();
1121    }
1122
1123    return ;
1124  }
1125
1126
1127  unsigned char *mint=light_lookup+min_light_level*256;
1128
1129  light_patch *first=make_patch_list(cx2-cx1+1,cy2-cy1+1,screenx,screeny);
1130
1131
1132  int ytry=(1<<ly_run),xtry=(1<<lx_run);
1133  int calcx_mask=(0xefffffff-(xtry-1));
1134  int calcy_mask=(0xefffffff-(ytry-1));
1135  int scr_w=sc->width();
1136  int dscr_w=out->width();
1137
1138  int prefix_x=(screenx&7);
1139  int prefix=screenx&7;
1140  if (prefix)
1141    prefix=8-prefix;
1142  int suffix_x=cx2-cx1-(screenx&7);
1143
1144  int inside_xoff=(screenx+7)&(~7);
1145
1146  int suffix=(cx2-cx1-prefix+1)&7;
1147
1148
1149  long remap_size=((cx2-cx1+1-prefix-suffix)>>lx_run);
1150
1151  uchar *remap_line=(uchar *)jmalloc(remap_size,"light remap line");
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164  light_patch *f=first;
1165  uchar *in_line=sc->scan_line(cy1)+cx1;
1166  uchar *out_line=out->scan_line(cy1*2+out_y)+cx1*2+out_x;
1167
1168
1169  for (int y=cy1;y<=cy2;)
1170  {
1171    int x,count;
1172//    while (f->next && f->y2<y)
1173//      f=f->next;
1174    uchar *rem=remap_line;
1175
1176    int todoy=4-((screeny+y)&3);
1177    if (y+todoy>cy2)
1178      todoy=cy2-y+1;
1179
1180    int calcy=((y+screeny)&(~3))-cy1;
1181   
1182
1183    if (suffix)
1184    {
1185      light_patch *lp=f;
1186      for (;(lp->y1>y-cy1 || lp->y2<y-cy1 ||
1187                              lp->x1>suffix_x || lp->x2<suffix_x);lp=lp->next);
1188      long caddr=(long)in_line+cx2-cx1+1-suffix;
1189      long daddr=(long)out_line+(cx2-cx1+1-suffix)*2;
1190
1191      uchar *r=light_lookup+(((long)calc_light_value(lp,suffix_x+screenx,calcy)<<8));
1192      switch (todoy)
1193      {
1194        case 4 :
1195        {
1196          MAP_2PUT(caddr,daddr,(long)r,suffix); daddr+=dscr_w;
1197          MAP_2PUT(caddr,daddr,(long)r,suffix); daddr+=dscr_w; caddr+=scr_w;
1198        }
1199        case 3 :
1200        {
1201          MAP_2PUT(caddr,daddr,(long)r,suffix); daddr+=dscr_w;
1202          MAP_2PUT(caddr,daddr,(long)r,suffix); daddr+=dscr_w; caddr+=scr_w;
1203        }
1204        case 2 :
1205        {
1206          MAP_2PUT(caddr,daddr,(long)r,suffix); daddr+=dscr_w;
1207          MAP_2PUT(caddr,daddr,(long)r,suffix); daddr+=dscr_w; caddr+=scr_w;
1208        }
1209        case 1 :
1210        {
1211          MAP_2PUT(caddr,daddr,(long)r,suffix); daddr+=dscr_w;
1212          MAP_2PUT(caddr,daddr,(long)r,suffix); daddr+=dscr_w; caddr+=scr_w;
1213        } break;
1214      }
1215    }
1216
1217    if (prefix)
1218    {
1219      light_patch *lp=f;
1220      for (;(lp->y1>y-cy1 || lp->y2<y-cy1 ||
1221                              lp->x1>prefix_x || lp->x2<prefix_x);lp=lp->next);
1222
1223      uchar *r=light_lookup+(((long)calc_light_value(lp,prefix_x+screenx,calcy)<<8));
1224      long caddr=(long)in_line;
1225      long daddr=(long)out_line;
1226      switch (todoy)
1227      {
1228        case 4 :
1229        {
1230          MAP_2PUT(caddr,daddr,(long)r,prefix); daddr+=dscr_w;
1231          MAP_2PUT(caddr,daddr,(long)r,prefix); daddr+=dscr_w; caddr+=scr_w;
1232        }
1233        case 3 :
1234        {
1235          MAP_2PUT(caddr,daddr,(long)r,prefix); daddr+=dscr_w;
1236          MAP_2PUT(caddr,daddr,(long)r,prefix); daddr+=dscr_w; caddr+=scr_w;
1237        }
1238        case 2 :
1239        {
1240          MAP_2PUT(caddr,daddr,(long)r,prefix); daddr+=dscr_w;
1241          MAP_2PUT(caddr,daddr,(long)r,prefix); daddr+=dscr_w; caddr+=scr_w;
1242        }
1243        case 1 :
1244        {
1245          MAP_2PUT(caddr,daddr,(long)r,prefix); daddr+=dscr_w;
1246          MAP_2PUT(caddr,daddr,(long)r,prefix); daddr+=dscr_w; caddr+=scr_w;
1247        } break;
1248      }
1249      in_line+=prefix;
1250      out_line+=prefix*2;
1251    }
1252
1253
1254 
1255
1256    for (x=prefix,count=0;count<remap_size;count++,x+=8,rem++)   
1257    {
1258      light_patch *lp=f;
1259      for (;(lp->y1>y-cy1 || lp->y2<y-cy1 || lp->x1>x || lp->x2<x);lp=lp->next);
1260      *rem=calc_light_value(lp,x+screenx,calcy);
1261    }
1262
1263    rem=remap_line;
1264
1265    put_8line(in_line,out_line,rem,light_lookup,count);
1266    memcpy(out_line+dscr_w,out_line,count*16);
1267    out_line+=dscr_w;
1268    in_line+=scr_w; out_line+=dscr_w; y++; todoy--;
1269    if (todoy)
1270    {
1271      put_8line(in_line,out_line,rem,light_lookup,count);
1272      memcpy(out_line+dscr_w,out_line,count*16);
1273      out_line+=dscr_w;
1274      in_line+=scr_w; out_line+=dscr_w; y++; todoy--;
1275      if (todoy)
1276      {
1277        put_8line(in_line,out_line,rem,light_lookup,count);
1278        memcpy(out_line+dscr_w,out_line,count*16);
1279        out_line+=dscr_w;
1280        in_line+=scr_w; out_line+=dscr_w; y++; todoy--;
1281        if (todoy)
1282        {
1283          put_8line(in_line,out_line,rem,light_lookup,count);
1284          memcpy(out_line+dscr_w,out_line,count*16);
1285          out_line+=dscr_w;
1286          in_line+=scr_w; out_line+=dscr_w; y++;
1287        }
1288      }
1289    }     
1290    in_line-=prefix;
1291    out_line-=prefix*2;
1292  }
1293
1294
1295  while (first)
1296  {
1297    light_patch *p=first;
1298    first=first->next;
1299    delete p;
1300  }
1301  jfree(remap_line);
1302}
1303
1304
1305
1306
1307void add_light_spec(spec_directory *sd, char *level_name)
1308{
1309  long size=4+4;  // number of lights and minimum light levels
1310  for (light_source *f=first_light_source;f;f=f->next)
1311    size+=6*4+1;
1312  sd->add_by_hand(new spec_entry(SPEC_LIGHT_LIST,"lights",NULL,size,0)); 
1313}
1314
1315void write_lights(bFILE *fp)
1316{
1317  int t=0;
1318  light_source *f=first_light_source;
1319  for (;f;f=f->next) t++;
1320  fp->write_long(t);
1321  fp->write_long(min_light_level);
1322  for (f=first_light_source;f;f=f->next)
1323  {
1324    fp->write_long(f->x);
1325    fp->write_long(f->y);
1326    fp->write_long(f->xshift);
1327    fp->write_long(f->yshift);
1328    fp->write_long(f->inner_radius);
1329    fp->write_long(f->outer_radius);
1330    fp->write_byte(f->type);
1331  }
1332}
1333
1334
1335void read_lights(spec_directory *sd, bFILE *fp, char *level_name)
1336{
1337  delete_all_lights();
1338  spec_entry *se=sd->find("lights");
1339  if (se)
1340  {
1341    fp->seek(se->offset,SEEK_SET);
1342    long t=fp->read_long();
1343    min_light_level=fp->read_long();
1344    light_source *last;
1345    while (t)
1346    {
1347      t--;
1348      long x=fp->read_long();
1349      long y=fp->read_long();
1350      long xshift=fp->read_long();
1351      long yshift=fp->read_long();
1352      long ir=fp->read_long();
1353      long ora=fp->read_long();
1354      long ty=fp->read_byte();
1355
1356      light_source *p=new light_source(ty,x,y,ir,ora,xshift,yshift,NULL);
1357     
1358      if (first_light_source)
1359        last->next=p;
1360      else first_light_source=p;
1361      last=p;
1362    }
1363  }
1364}
1365
1366
1367
1368
1369
1370
Note: See TracBrowser for help on using the repository browser.