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

Last change on this file since 494 was 494, checked in by Sam Hocevar, 12 years ago

style: remove trailing spaces, fix copyright statements.

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