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

Last change on this file since 512 was 512, checked in by Sam Hocevar, 7 years ago

imlib: use vec2i for image::size and unroll all necessary changes
everywhere else in the code.

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