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

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