source: abuse/trunk/src/imlib/specs.cpp @ 4

Last change on this file since 4 was 4, checked in by Sam Hocevar, 17 years ago
  • debian patches
File size: 20.9 KB
Line 
1#include "image.hpp"
2#include "palette.hpp"
3#include "specs.hpp"
4#include <stdio.h>
5#include <stdlib.h>
6#include <ctype.h>
7#include <fcntl.h>
8#include "system.h"
9#include "jmalloc.hpp"
10#include <math.h>
11#include "dprint.hpp"
12#if (defined(__MACH__) || !defined(__APPLE__))
13#include <sys/types.h>
14#include <sys/stat.h>
15#endif
16
17#if (defined(__APPLE__) && !defined(__MACH__))
18extern char *macify_name(char *s);
19#endif
20
21char *spec_types[]={"Invalid type",             // 0
22                    "Color table",              // 1
23                    "Palette",                  // 2
24                    "Invalid Type",             // 3
25                    "Image",                    // 4
26                                        "Fore Tile",
27                    "Back Tile",
28                    "Character",
29                    "8 Morph",
30                    "16 Morph",
31                    "Grue objs",
32                    "Extern WAV",
33                    "DMX MUS",
34                    "Patched morph",
35                    "Normal file",
36                    "Compress1 file",
37                    "Vector Image",
38                    "Light list",
39                    "Grue fgmap",
40                    "Grue bgmap",
41                    "Data array",
42                    "Character2",
43                    "Particle",
44                    "Extern lcache"
45};
46
47
48int total_files_open=0;
49char spec_main_file[100];
50
51static char *spec_prefix=NULL;
52static char *save_spec_prefix=NULL;
53
54static jFILE spec_main_jfile((FILE*)0);
55static int spec_main_fd = -1;
56static long spec_main_offset = -1;
57static spec_directory spec_main_sd;
58
59static int fast_load_fd = -1;
60static int fast_load_mode = 0;
61
62void set_filename_prefix(char *prefix)
63{
64        if( spec_prefix )
65        {
66                jfree( spec_prefix );
67        }
68       
69        if( prefix )
70        {
71                spec_prefix = strcpy( (char *)jmalloc( strlen( prefix ) + 2, "prefix_name" ), prefix );
72                int len = strlen( prefix );
73                if( prefix[len - 1] != '\\' && prefix[len - 1] != '/')
74                {
75                        spec_prefix[len] = '/';
76                        spec_prefix[len + 1] = 0;
77                }
78        }
79        else
80        {
81                spec_prefix = NULL;
82        }
83}
84
85char *get_filename_prefix()
86{
87        return spec_prefix;
88}
89
90
91void set_save_filename_prefix(char *save_prefix)
92{
93        if( save_spec_prefix )
94        {
95                jfree( save_spec_prefix );
96        }
97
98        if( save_prefix )
99        {
100                int len = strlen( save_prefix );
101                save_spec_prefix = (char *)jmalloc( len + 1, "prefix_name" );
102                strcpy( save_spec_prefix, save_prefix );
103/* AK - Commented this out as it may cause problems
104                if( save_prefix[len - 1] != '\\' && save_prefix[len - 1] != '/' )
105                {
106                        save_spec_prefix[len] = '/';
107                        save_spec_prefix[len + 1] = '\0';
108                } */
109        }
110        else
111        {
112                save_spec_prefix = NULL;
113        }
114}
115
116char *get_save_filename_prefix()
117{
118  return save_spec_prefix;
119}
120
121int search_order=SPEC_SEARCH_OUTSIDE_INSIDE;
122
123static void (*no_space_handle_fun)()=NULL;
124
125void set_no_space_handler(void (*handle_fun)())
126{
127  no_space_handle_fun=handle_fun;
128}
129
130
131bFILE::bFILE()
132{
133  rbuf_size=8192;
134  rbuf=(unsigned char *)jmalloc(rbuf_size,"File read buffer");
135  rbuf_start=rbuf_end=0; 
136
137  wbuf_size=8192;
138  wbuf=(unsigned char *)jmalloc(wbuf_size,"File write buffer");
139  wbuf_end=0; 
140}
141
142bFILE::~bFILE()
143{
144  if (rbuf) jfree(rbuf);
145  flush_writes();
146  if (wbuf) jfree(wbuf);
147}
148
149int bFILE::flush_writes()
150{
151  if (wbuf_end!=0)
152  {
153    unsigned long ret=unbuffered_write(wbuf,wbuf_end);
154    if (ret!=wbuf_end && no_space_handle_fun)
155      no_space_handle_fun();
156     
157    wbuf_end=0;
158    return ret;
159  }
160  return 0;
161}
162
163int bFILE::read(void *buf, size_t count)       // returns number of bytes read, calls unbuffer_read
164{
165  if (!allow_read_buffering())
166    return unbuffered_read(buf,count);
167
168  int total_read=0,error=0;
169  if (!count) return 0;
170  while (count && !error)
171  {
172    if (rbuf_start<rbuf_end)
173    {
174      unsigned int avail_size=rbuf_end-rbuf_start;
175      int copy_size=avail_size>count ? count : avail_size;
176      memcpy(buf,rbuf+rbuf_start,copy_size);
177      buf=(void *)(((unsigned char *)buf)+copy_size);
178      rbuf_start+=copy_size;
179      if (rbuf_start>=rbuf_end)   
180      {
181                                if (rbuf_end!=rbuf_size)  // buffer wasn't full before so there is no way we can complete read
182                                  error=1;
183                                rbuf_start=rbuf_end=0;
184      }
185      total_read+=copy_size;
186      count-=copy_size;
187    } else
188    {
189      rbuf_end=unbuffered_read(rbuf,rbuf_size);
190      if (rbuf_end==0) error=1;
191      rbuf_start=0;
192    }
193  }
194  return total_read;
195}
196
197
198int bFILE::write(void *buf, size_t count)      // returns number of bytes written
199{
200  if (allow_write_buffering())
201  {
202    int total_written=0;
203    while (count)
204    {
205      int copy_size=wbuf_end+count<=wbuf_size ? count :  wbuf_size-wbuf_end;           
206      memcpy(wbuf+wbuf_end,buf,copy_size);
207      wbuf_end+=copy_size;
208      count-=copy_size;
209      buf=(void *)(((char *)buf)+copy_size);
210      if (wbuf_end==wbuf_size)
211        if ((unsigned int)flush_writes()!=wbuf_size)
212          return total_written;
213     
214      total_written+=copy_size;     
215    }
216    return total_written;
217  } else
218  {
219    unsigned long ret=unbuffered_write(buf,count);
220    if (ret!=count && no_space_handle_fun)
221      no_space_handle_fun();
222  }
223  return 0;
224}
225
226int bFILE::seek(long offset, int whence) // whence=SEEK_SET, SEEK_CUR, SEEK_END, ret=0=success
227
228//    rbuf_start=rbuf_end=0;
229//    unbuffered_seek(offset,SEEK_SET);
230
231  long realpos=unbuffered_tell();
232  long curpos=realpos-rbuf_end+rbuf_start;
233  if (whence==SEEK_CUR) offset+=curpos;
234  else if (whence==SEEK_END) offset=file_size()-offset;
235
236  if (offset<realpos-(long)rbuf_end || offset>=realpos)
237  {
238    rbuf_start=rbuf_end=0;
239    unbuffered_seek(offset,SEEK_SET);
240  } else 
241    rbuf_start=rbuf_end-(realpos-offset);
242  return 1;
243}
244
245int bFILE::tell()
246{
247  return unbuffered_tell()-rbuf_end+rbuf_start+
248         wbuf_end;    // if this a write file, add on how much we've written
249}
250
251int bFILE::allow_read_buffering() { return 1; }
252int bFILE::allow_write_buffering() { return 1; }
253
254void bFILE::set_read_buffer_size(long size)
255{
256  unbuffered_seek(tell(),SEEK_SET);
257  rbuf_start=rbuf_end=0;
258  if (rbuf)
259    jfree(rbuf);
260  rbuf_size=size;
261  rbuf=(unsigned char *)jmalloc(rbuf_size,"File buffer");
262}
263
264void set_spec_main_file(char *filename, int Search_order)
265{
266  dprintf("Specs : main file set to %s\n",filename);
267  strcpy(spec_main_file,filename);
268  search_order=Search_order;
269 
270#if (defined(__APPLE__) && !defined(__MACH__))
271  spec_main_jfile.open_external(filename,"rb",O_BINARY|O_RDONLY);
272#else
273  spec_main_jfile.open_external(filename,"rb",O_RDONLY);
274#endif
275  spec_main_fd = spec_main_jfile.get_fd();
276  if (spec_main_fd==-1)
277    return;
278  spec_main_sd.startup(&spec_main_jfile);
279}
280
281void fast_load_start_recording(char *filename)
282{
283#if (defined(__APPLE__) && !defined(__MACH__))
284  fast_load_fd = ::open(macify_name(filename),O_BINARY|O_CREAT|O_RDWR);
285#else
286  fast_load_fd = ::open(filename,O_CREAT|O_RDWR,S_IRWXU | S_IRWXG | S_IRWXO);
287#endif
288        fast_load_mode = 1;
289}
290
291void fast_load_stop_recording()
292{
293        fast_load_mode = 0;
294}
295
296void fast_load_start_reloading(char *filename)
297{
298#if (defined(__APPLE__) && !defined(__MACH__))
299  fast_load_fd = ::open(macify_name(filename),O_BINARY|O_RDONLY);
300#else
301  fast_load_fd = ::open(filename,O_RDONLY);
302#endif
303        fast_load_mode = 2;
304}
305
306void fast_load_stop_reloading()
307{
308        fast_load_mode = 0;
309}
310
311jFILE::jFILE(FILE *file_pointer)                       // assumes fp is at begining of file
312{
313  access=0;
314  fd=-1;
315  file_length=0;
316  start_offset=0;
317  flags=JFILE_CLONED;
318}
319
320void jFILE::open_external(char *filename, char *mode, int flags)
321{
322  int skip_size=0;
323  char tmp_name[200];
324  if (spec_prefix && filename[0] != '/')
325    sprintf(tmp_name,"%s%s",spec_prefix,filename);
326  else strcpy(tmp_name,filename);
327
328//  int old_mask=umask(S_IRWXU | S_IRWXG | S_IRWXO);
329#ifdef __WATCOMC__
330  flags|=O_BINARY;
331#endif
332  if (flags&O_WRONLY)
333  {
334    if ((flags&O_APPEND)==0)
335    {
336      skip_size=1;
337      //int errval = unlink(tmp_name);
338    }
339
340    flags-=O_WRONLY;
341    flags|=O_CREAT|O_RDWR;
342
343#if (defined(__APPLE__) && !defined(__MACH__))
344    fd=open(macify_name(tmp_name),flags);
345#else
346    fd=open(tmp_name,flags,S_IRWXU | S_IRWXG | S_IRWXO);
347#endif
348  } else
349#if (defined(__APPLE__) && !defined(__MACH__))
350    fd=open(macify_name(tmp_name),flags);
351#else
352    fd=open(tmp_name,flags);
353#endif
354
355//  umask(old_mask);
356  if (fd>=0 && !skip_size)
357  {
358    file_length=lseek(fd,0,SEEK_END);
359    if ((flags&O_APPEND)==0)
360      lseek(fd,0,SEEK_SET);
361    else
362        current_offset = file_length;
363    start_offset=0;
364  } else
365  {
366    file_length=0;
367    start_offset=0;
368  }
369}
370
371
372class null_file : public bFILE     // this file type will use virtual opens inside of a spe
373{
374  public :
375  virtual int open_failure() { return 1; }
376  virtual int unbuffered_read(void *buf, size_t count)   { return 0; }
377  virtual int unbuffered_write(void *buf, size_t count)  { return 0; }
378  virtual int unbuffered_seek(long offset, int whence)   { return 0; }
379
380  virtual int unbuffered_tell() { return 0; }
381  virtual int file_size() { return 0; }
382  virtual ~null_file() { ; }
383} ;
384
385
386static bFILE *(*open_file_fun)(char *,char *)=NULL;
387int (*verify_file_fun)(char *,char *)=NULL;
388
389void set_file_opener(bFILE *(*open_fun)(char *, char *))
390{
391  open_file_fun=open_fun;
392}
393
394bFILE *open_file(char *filename, char *mode)
395{
396  if (!verify_file_fun || verify_file_fun(filename,mode))
397  {
398    if (open_file_fun)
399      return open_file_fun(filename,mode);
400    else return new jFILE(filename,mode);
401  } else return new null_file;
402}
403
404void jFILE::open_internal(char *filename, char *mode, int flags)
405{
406  int wr=0;
407  for (char *s=mode;*s;s++)
408    if (toupper(*s)=='A' || toupper(*s)=='W')
409      wr=1;
410
411  if (wr)
412    fd=-1;                 // only allow extern file openings for writing
413  else
414  {
415        fd = spec_main_fd;
416    if (fd>=0)                    // if we were able to open the main file, see if it's in there
417    {
418      start_offset=0;
419      spec_entry *se=spec_main_sd.find(filename);
420      if (se)   
421      {
422                                start_offset=se->offset;
423                                current_offset = 0;
424                                file_length=se->size;
425                                rbuf_start=rbuf_end=0;
426      } else
427      {
428                                close(fd);
429                                fd=-1;
430      }
431    } 
432  }
433}
434
435jFILE::jFILE(char *filename, char *access_string)      // same as fopen parameters
436{
437 flags=access=0; 
438 char *s=access_string;
439  for (;*s;s++)
440    if (toupper(*s)=='R') access=O_RDONLY;
441
442  for (s=access_string;*s;s++)
443    if (toupper(*s)=='W')     
444      if (access)
445        access=O_RDWR;
446      else access=O_WRONLY;
447
448  for (s=access_string;*s;s++)
449    if (toupper(*s)=='A')     
450      access|=O_APPEND|O_WRONLY;
451
452  file_length=start_offset=-1;
453  current_offset = 0;
454
455  fd=-1;
456  if (search_order==SPEC_SEARCH_OUTSIDE_INSIDE)
457    open_external(filename,access_string,access);
458
459  if (fd<0)
460    open_internal(filename,access_string,access);
461
462  if (fd<0 && search_order==SPEC_SEARCH_INSIDE_OUTSIDE)
463    open_external(filename,access_string,access);
464
465  total_files_open++;
466}
467
468jFILE::~jFILE()
469{
470  flush_writes();
471  if (fd>=0 && !(flags&JFILE_CLONED))
472  {
473    total_files_open--;
474    if (fd != spec_main_fd)
475            close(fd);
476  }
477}
478
479int jFILE::unbuffered_tell()
480{
481//      int ret = ::lseek(fd,0,SEEK_CUR) - start_offset;
482//      if (ret != current_offset)
483//              fprintf(stderr,"Bad tell %d\n",current_offset);
484        return current_offset;
485}
486
487int jFILE::unbuffered_read(void *buf, size_t count)
488{
489        unsigned long len;
490
491        if (fd == spec_main_fd)
492        {
493                switch (fast_load_mode)
494                {
495                case 0:
496                        if (current_offset+start_offset != spec_main_offset)
497                                spec_main_offset = lseek(fd, start_offset+current_offset, SEEK_SET);
498                       
499                        len = ::read(fd,(char*)buf,count);
500                        break;
501                case 1:
502                        if (current_offset+start_offset != spec_main_offset)
503                                spec_main_offset = lseek(fd, start_offset+current_offset, SEEK_SET);
504                       
505                        len = ::read(fd,(char*)buf,count);
506                        ::write(fast_load_fd,(char*)&len,sizeof(len));
507                        ::write(fast_load_fd,(char*)buf,len);
508                        break;
509                case 2:
510                        ::read(fast_load_fd,(char*)&len,sizeof(len));
511                        len = ::read(fast_load_fd,(char*)buf,len);
512                        break;
513                }
514               
515                spec_main_offset += len;
516        }
517        else
518        {
519                switch (fast_load_mode)
520                {
521                case 0:
522                len = ::read(fd,(char*)buf,count);
523                break;
524                case 1:
525                len = ::read(fd,(char*)buf,count);
526                        ::write(fast_load_fd,(char*)&len,sizeof(len));
527                        ::write(fast_load_fd,(char*)buf,len);
528                break;
529                case 2:
530                        ::read(fast_load_fd,(char*)&len,sizeof(len));
531                        len = ::read(fast_load_fd,(char*)buf,len);
532                        if (count != len)
533                                printf("short read! %ld:%ld\n",current_offset,len);
534                break;
535          }
536        }
537        current_offset += len;
538        return len;
539}
540
541int jFILE::unbuffered_write(void *buf, size_t count)
542{
543  long ret = ::write(fd,(char*)buf,count);
544        current_offset += ret;
545        return ret;
546}
547
548int jFILE::unbuffered_seek(long offset, int whence) // whence=SEEK_SET, SEEK_CUR, SEEK_END, ret=0=success
549{
550        long ret;
551       
552        if (fast_load_mode == 2)
553        {
554                switch (whence)
555                {
556    case SEEK_SET :
557        current_offset = start_offset+offset;
558        break;
559    case SEEK_END :
560        current_offset = start_offset+file_length-offset;
561        break;
562    case SEEK_CUR :
563        current_offset += offset;
564        break;
565    default:
566        ret = -1;
567        break;
568    }
569                return current_offset;
570        }
571       
572  switch (whence)
573  {
574    case SEEK_SET :
575    { ret = lseek(fd,start_offset+offset,SEEK_SET); } break;
576    case SEEK_END :
577    { ret = lseek(fd,start_offset+file_length-offset,SEEK_SET); } break;
578    case SEEK_CUR :
579    { ret = lseek(fd,offset,SEEK_CUR); } break;
580    default:
581        ret = -1;
582        break;
583  }
584  if (ret>=0)
585  {
586        current_offset = ret - start_offset;
587        if (spec_main_fd == fd)
588                spec_main_offset = ret;
589        return ret;
590  }
591  else
592          return -1;  // if a bad whence, then failure
593}
594
595
596unsigned char bFILE::read_byte()
597{ unsigned char x;
598  read(&x,1);
599  return x;
600}
601
602unsigned short bFILE::read_short()
603{
604  unsigned short x;
605  read(&x,2);
606  return int_to_local(x);
607}
608
609
610unsigned long bFILE::read_long()
611{
612  unsigned long x;
613  read(&x,4);
614  return long_to_local(x);
615}
616
617void bFILE::write_byte(unsigned char x)
618{
619  write(&x,1);
620}
621
622void bFILE::write_short(unsigned short x)
623{
624  x=int_to_local(x);
625  write(&x,2);
626}
627
628
629void bFILE::write_long(unsigned long x)
630{
631  x=long_to_local(x);
632  write(&x,4);
633}
634
635void bFILE::write_double(double x)
636{
637  double a;
638  write_long((long)(modf(x,&a)*(double)(1<<32-1)));
639  write_long((long)a);
640}
641
642double bFILE::read_double()
643{
644  long a,b;
645  a=read_long();
646  b=read_long();
647  return (double)b+a/(double)(1<<32-1);
648}
649
650spec_directory::~spec_directory()
651{
652
653  if (total)
654  {
655    jfree(data);
656    jfree(entries);
657  }
658}
659
660void spec_entry::print()
661{
662  printf("%15s%25s%8ld%8ld\n",spec_types[type],name,size,offset);
663}
664
665void spec_directory::calc_offsets()
666{
667  spec_entry **e;
668  int i;
669  long o=SPEC_SIG_SIZE+2;
670  if (total)
671  {
672    for (i=0,e=entries;i<total;i++,e++)          // calculate the size of directory info
673    {
674      o+=1+1+strlen((*e)->name)+1 +1 +8;
675    }
676
677    for (i=0,e=entries;i<total;i++,e++)          // calculate offset for each entry
678    {
679      (*e)->offset=o;
680      o+=(*e)->size;
681    }
682  }
683}
684
685spec_entry *spec_directory::find(char *name, int type)
686{
687  int i;
688  spec_entry **e;
689  for (i=0,e=entries;i<total;i++,e++)
690    if (!strcmp((*e)->name,name) && (*e)->type==type)
691      return (*e);
692  return NULL;
693}
694
695spec_entry *spec_directory::find(char *name)
696{
697  int i;
698  spec_entry **e;
699  for (i=0,e=entries;i<total;i++,e++)
700    if (!strcmp((*e)->name,name))
701      return (*e);
702  return NULL;
703}
704
705long spec_directory::find_number(char *name)
706{
707  int i;
708  spec_entry **e;
709  for (i=0,e=entries;i<total;i++,e++)
710    if (!strcmp((*e)->name,name))
711      return i;
712  return -1;
713}
714
715spec_entry *spec_directory::find(int type)
716{
717  int i;
718  spec_entry **e;
719  for (i=0,e=entries;i<total;i++,e++)
720    if ((*e)->type==type)
721      return (*e);
722  return NULL;
723}
724
725long spec_directory::type_total(int type)
726{
727  int i,x=0;
728  spec_entry **e;
729  for (i=0,e=entries;i<total;i++,e++)
730    if ((*e)->type==type) x++;
731  return x;
732}
733
734long spec_directory::find_number(int type)
735{
736  int i;
737  spec_entry **e;
738  for (i=0,e=entries;i<total;i++,e++)
739    if ((*e)->type==type)
740      return i;
741  return -1;
742}
743
744void spec_directory::print()
745{
746  spec_entry **se;
747  int i;
748  printf("[   Entry type   ][   Entry name   ][  Size  ][ Offset ]\n");
749  for (i=0,se=entries;i<total;i++,se++)
750    (*se)->print();
751}
752
753
754void spec_directory::startup(bFILE *fp)
755{
756  char buf[256];
757  memset(buf,0,256);
758  fp->read(buf,8);
759  buf[9]=0;
760  size=0;
761  if (!strcmp(buf,SPEC_SIGNATURE))
762  {   
763    total=fp->read_short();   
764    entries=(spec_entry **)jmalloc(sizeof(spec_entry *)*total,"spec_directory::entries");
765    long start=fp->tell();
766
767    int i;
768    for (i=0;i<total;i++)
769    {           
770      fp->read(buf,2);
771      long entry_size=sizeof(spec_entry)+(unsigned char)buf[1];
772      entry_size=(entry_size+3)&(~3);
773      fp->read(buf,(unsigned char)buf[1]);
774      fp->read(buf,9);
775
776      size+=entry_size;
777    }
778    data=jmalloc(size,"spec_directory::data");
779    char *dp=(char *)data;
780    fp->seek(start,SEEK_SET);
781    for (i=0;i<total;i++)
782    {           
783      spec_entry *se=(spec_entry *)dp;
784      entries[i]=se;
785
786      unsigned char len,flags,type;
787      fp->read(&type,1);     
788      fp->read(&len,1);
789      se->type=type;
790      se->name=dp+sizeof(spec_entry);
791      fp->read(se->name,len);
792      fp->read(&flags,1);
793
794      se->size=fp->read_long();
795      se->offset=fp->read_long();
796      dp+=((sizeof(spec_entry)+len)+3)&(~3);
797    }
798  }
799  else
800  {
801    total=0;
802    data=NULL;
803    entries=NULL;
804  } 
805}
806
807
808spec_directory::spec_directory(bFILE *fp)
809{ startup(fp); }
810
811spec_directory::spec_directory(FILE *fp)
812{
813  jFILE jfp(fp);
814  startup(&jfp);
815}
816
817spec_directory::spec_directory()
818{
819  size=0;
820  total=0;
821  data=NULL;
822  entries=NULL;
823}
824
825/*
826spec_directory::spec_directory(char *filename)
827{
828  jFILE *fp;
829  if (filename)
830  {
831    fp=new jFILE(filename,"rb");
832    if (!fp->open_failure())
833      startup(fp);
834    else
835    {
836      total=0;
837      entries=NULL;
838    }
839    delete fp;
840  } else printf("NULL filename to spec_directory::spec_directory\n");
841}*/
842
843int write_string(bFILE *fp, char *st)
844{
845  unsigned char length=strlen(st)+1;
846  if (fp->write(&length,1)!=1) return 0;
847  if (fp->write(st,length)!=length) return 0;
848  return 1;
849}
850
851long spec_directory::data_start_offset()
852{
853  long i;
854  for (i=0;i<total;i++)
855    return entries[i]->offset;
856
857  return SPEC_SIG_SIZE+2;     // if no entries, then no data, but return where it would
858                              // start anyway
859}
860
861long spec_directory::data_end_offset()
862{
863  spec_entry **e;
864  long i;
865  for (i=total-1,e=entries;i>=0;i--,e++)
866    return (*e)->offset+(*e)->size;
867
868  return SPEC_SIG_SIZE+2;
869}
870
871int spec_directory::write(bFILE *fp)
872{
873
874  char sig[SPEC_SIG_SIZE];
875  unsigned char flags=0;
876  unsigned long offset,data_size;
877  spec_entry **e;
878  strcpy(sig,SPEC_SIGNATURE);
879
880  if (fp->write(sig,sizeof(sig))!=sizeof(sig))    return 0;
881  fp->write_short(total);
882
883
884  int i;
885  for (i=0,e=entries;i<total;i++,e++)
886  {
887    if (fp->write(&(*e)->type,1)!=1)                 return 0;
888    if (!write_string(fp,(*e)->name))                return 0;
889    flags=0;
890    if (fp->write(&flags,1)!=1)                     return 0;
891
892    data_size=long_to_intel((*e)->size);
893    if (fp->write((char *)&data_size,4)!=4)              return 0;
894    offset=long_to_intel((*e)->offset);
895    if (fp->write((char *)&offset,4)!=4)                  return 0;
896
897  }
898  return 1;
899}
900
901jFILE *spec_directory::write(char *filename)
902{
903  jFILE *fp;
904  fp=new jFILE(filename,"wb");
905  if (fp->open_failure()) { delete fp; return NULL; }
906  if (!write(fp))
907  {
908    delete fp;
909    return NULL;
910  } else return fp;
911
912}
913
914unsigned short read_short(FILE *fp)
915{
916  unsigned short x;
917  fread(&x,1,2,fp);
918  return int_to_local(x);
919}
920
921unsigned long read_long(FILE *fp)
922{
923  unsigned long x;
924  fread(&x,1,4,fp);
925  return (long)long_to_local(x);
926}
927void write_short(FILE *fp, unsigned short x)
928{
929  x=int_to_local(x);
930  fwrite(&x,1,2,fp);
931}
932
933void write_long(FILE *fp, unsigned long x)
934{
935  x=long_to_local(x);
936  fwrite(&x,1,4,fp);
937}
938
939unsigned char read_byte(FILE *fp) { return fgetc(fp)&0xff; }
940void write_byte(FILE *fp, unsigned char x) { fputc(x,fp); }
941
942unsigned short read_other_long(FILE *fp)
943{
944  unsigned long x;
945  fread(&x,1,4,fp);
946  return big_long_to_local(x);
947}
948
949unsigned long read_other_short(FILE *fp)
950{
951  unsigned short x;
952  fread(&x,1,2,fp);
953  return big_short_to_local(x);
954}
955
956
957void write_other_short(FILE *fp, unsigned short x)
958{
959  x=big_short_to_local(x);
960  fwrite(&x,1,2,fp);
961}
962
963void write_other_long(FILE *fp, unsigned long x)
964{
965  x=big_long_to_local(x);
966  fwrite(&x,1,4,fp);
967}
968
969void spec_directory::remove(spec_entry *e)
970{
971  int i;
972  for (i=0;i<total && entries[i]!=e;i++);            // find the entry in the array first
973 
974  if (entries[i]==e)                                 // make sre it was found
975  {
976    delete e;
977    total--;
978    for (;i<total;i++)                               // compact the pointer array
979      entries[i]=entries[i+1];
980    entries=(spec_entry **)jrealloc(entries,sizeof(spec_entry *)*total,"spec_directory::entries");
981  }
982  else
983    printf("Spec_directory::remove bad entry pointer\n");
984}
985
986
987
988void spec_directory::add_by_hand(spec_entry *e)
989{
990  total++;
991  entries=(spec_entry **)jrealloc(entries,sizeof(spec_entry *)*total,"spec_directory::entries");
992  entries[total-1]=e;
993}
994
995void spec_directory::delete_entries()   // if the directory was created by hand instead of by file
996{
997  int i;
998  for (i=0;i<total;i++)
999    delete entries[i];
1000
1001  if (total)
1002    jfree(entries);
1003}
1004
1005
1006void note_open_fd(int fd, char *str)
1007{
1008  total_files_open++;
1009}
1010
1011void note_close_fd(int fd)
1012{
1013  total_files_open--;
1014}
1015
1016
1017void list_open_fds()
1018{
1019  printf("Total open dos fds=%d\n",total_files_open);
1020}
1021
Note: See TracBrowser for help on using the repository browser.