NXEngine v1.0.0.6
[NXEngine.git] / siflib / sifloader.cpp
blob854f9fea026847514ea9251a8dd4b5640a6c085a
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include "sifloader.h"
6 #include "sifloader.fdh"
8 #define SIF_MAGICK 'SIF2' // SIF magick and version denotation; first 4 bytes of file
10 SIFLoader::SIFLoader()
12 fFP = NULL;
15 SIFLoader::~SIFLoader()
17 ClearIndex();
18 if (fFP) fclose(fFP);
22 void c------------------------------() {}
25 void SIFLoader::ClearIndex()
27 for(int i=0;;i++)
29 SIFIndexEntry *entry = (SIFIndexEntry *)fIndex.ItemAt(i);
30 if (!entry) break;
32 if (entry->data) free(entry->data);
33 delete entry;
36 fIndex.MakeEmpty();
39 void SIFLoader::CloseFile()
41 ClearIndex();
43 if (fFP)
45 fclose(fFP);
46 fFP = NULL;
51 void c------------------------------() {}
54 bool SIFLoader::LoadHeader(const char *filename)
56 FILE *fp;
57 uint32_t magick;
59 ClearIndex();
61 if (fFP) fclose(fFP);
62 fp = fFP = fileopen(filename, "rb");
64 if (!fp)
66 staterr("SIFLoader::LoadHeader: failed to open file '%s'", filename);
67 return 1;
70 if ((magick = fgetl(fp)) != SIF_MAGICK)
72 staterr("SIFLoader::LoadHeader: magick check failed--this isn't a SIF file or is wrong version?");
73 staterr(" (expected %08x, got %08x)", SIF_MAGICK, magick);
74 return 1;
77 int nsections = fgetc(fp);
78 stat("SIFLoader::LoadHeader: read index of %d sections", nsections);
80 for(int i=0;i<nsections;i++)
82 SIFIndexEntry *entry = new SIFIndexEntry;
84 entry->type = fgetc(fp); // section type
85 entry->foffset = fgetl(fp); // absolute offset in file
86 entry->length = fgetl(fp); // length of section data
87 entry->data = NULL; // we won't load it until asked
89 fIndex.AddItem(entry);
90 //stat(" - Sect%02d @ %04x", entry->type, entry->foffset);
93 // ..leave file handle open, its ok
94 return 0;
97 // load into memory and return a pointer to the section of type 'type',
98 // or NULL if the file doesn't have a section of that type.
99 uint8_t *SIFLoader::FindSection(int type, int *length_out)
101 // try and find the section in the index
102 for(int i=0;;i++)
104 SIFIndexEntry *entry = (SIFIndexEntry *)fIndex.ItemAt(i);
105 if (!entry) break;
107 if (entry->type == type)
108 { // got it!
110 // haven't loaded it yet? need to fetch it from file?
111 if (!entry->data)
113 if (!fFP)
115 staterr("SIFLoader::FindSection: entry found and need to load it, but file handle closed");
116 if (length_out) *length_out = 0;
117 return NULL;
120 stat("Loading SIF section %d from address %04x", type, entry->foffset);
122 entry->data = (uint8_t *)malloc(entry->length);
123 fseek(fFP, entry->foffset, SEEK_SET);
124 fread(entry->data, entry->length, 1, fFP);
127 if (length_out) *length_out = entry->length;
128 return entry->data;
132 if (length_out) *length_out = 0;
133 return NULL;
137 void c------------------------------() {}
140 bool SIFLoader::BeginSave()
142 fTotalDataAdded = 0;
143 if (fFP) { fclose(fFP); fFP = NULL; }
144 ClearIndex();
145 return 0;
148 bool SIFLoader::AddSection(int type, uint8_t *data, int datalen)
150 SIFIndexEntry *entry = new SIFIndexEntry;
152 entry->type = type;
153 entry->foffset = fTotalDataAdded; // not including index tables or header, yet
154 entry->length = datalen;
155 entry->data = data;
157 fTotalDataAdded += datalen;
158 fIndex.AddItem(entry);
159 return 0;
162 bool SIFLoader::EndSave(const char *filename)
164 FILE *fp;
166 fp = fileopen(filename, "wb");
167 if (!fp)
169 stat("SIFLoader::EndSave: failed to open '%s' for writing", filename);
170 return 1;
173 // write header-header
174 fputl(SIF_MAGICK, fp);
175 fputc(fIndex.CountItems(), fp);
177 // compute fianl length of index table so we can write the correct foffsets
178 int indexlen = 5 + (fIndex.CountItems() * 9);
180 // write index table
181 for(int i=0;;i++)
183 SIFIndexEntry *entry = (SIFIndexEntry *)fIndex.ItemAt(i);
184 if (!entry) break;
186 fputc(entry->type, fp);
187 fputl(entry->foffset + indexlen, fp);
188 fputl(entry->length, fp);
191 // save actual section data
192 for(int i=0;;i++)
194 SIFIndexEntry *entry = (SIFIndexEntry *)fIndex.ItemAt(i);
195 if (!entry) break;
197 fwrite(entry->data, entry->length, 1, fp);
200 fclose(fp);
201 return 0;