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

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