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

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