source: rtems/c/src/lib/libbsp/arm/nds/tools/ndstool/source/ndsextract.cpp @ 2c63d97

4.104.115
Last change on this file since 2c63d97 was 2c63d97, checked in by Ralf Corsepius <ralf.corsepius@…>, on Dec 7, 2009 at 9:34:38 AM

2009-12-07 Ralf Corsépius <ralf.corsepius@…>

  • ndstool/source/ndsextract.cpp: Add missing const's.
  • Property mode set to 100644
File size: 6.9 KB
Line 
1#include "ndstool.h"
2#include "overlay.h"
3#include <errno.h>
4
5/*
6 * MkDir
7 */
8void MkDir(char *name)
9{
10#ifdef __MINGW32__
11        if (mkdir(name))
12#else
13        if (mkdir(name, S_IRWXU))
14#endif
15        {
16                if (errno != EEXIST)
17                {
18                        fprintf(stderr, "Cannot create directory '%s'.\n", name);
19                        exit(1);
20                }
21        }
22}
23
24/*
25 * ExtractFile
26 * if rootdir==0 nothing will be written
27 */
28void ExtractFile(char *rootdir, const char *prefix, char *entry_name, unsigned int file_id)
29{
30        unsigned int save_filepos = ftell(fNDS);
31
32        // read FAT data
33        fseek(fNDS, header.fat_offset + 8*file_id, SEEK_SET);
34        unsigned_int top;
35        fread(&top, 1, sizeof(top), fNDS);
36        unsigned_int bottom;
37        fread(&bottom, 1, sizeof(bottom), fNDS);
38        unsigned int size = bottom - top;
39        if (size > (1U << (17 + header.devicecap))) { fprintf(stderr, "File %u: Size is too big. FAT offset 0x%X contains invalid data.\n", file_id, header.fat_offset + 8*file_id); exit(1); }
40
41        // print file info
42        if (!rootdir || verbose)
43        {
44                printf("%5u 0x%08X 0x%08X %9u %s%s\n", file_id, (int)top, (int)bottom, size, prefix, entry_name);
45        }
46
47        // extract file
48        if (rootdir)
49        {
50                // make filename
51                char filename[MAXPATHLEN];
52                strcpy(filename, rootdir);
53                strcat(filename, prefix);
54                strcat(filename, entry_name);
55
56                fseek(fNDS, top, SEEK_SET);
57                FILE *fo = fopen(filename, "wb");
58                if (!fo) { fprintf(stderr, "Cannot create file '%s'.\n", filename); exit(1); }
59                while (size > 0)
60                {
61                        unsigned char copybuf[1024];
62                        unsigned int size2 = (size >= sizeof(copybuf)) ? sizeof(copybuf) : size;
63                        fread(copybuf, 1, size2, fNDS);
64                        fwrite(copybuf, 1, size2, fo);
65                        size -= size2;
66                }
67                fclose(fo);
68        }
69
70        fseek(fNDS, save_filepos, SEEK_SET);
71}
72
73/*
74 * MatchName
75 */
76bool MatchName(char *name, char *mask, int level=0)
77{
78        char *a = name;
79        char *b = mask;
80        //for (int i=0; i<level; i++) printf("  "); printf("matching a='%s' b='%s'\n", a, b);
81        while (1)
82        {
83                //for (int i=0; i<level; i++) printf("a=%s b=%s\n", a, b);
84                if (*b == '*')
85                {
86                        while (*b == '*') b++;
87        //for (int i=0; i<level; i++) printf("  "); printf("* '%s' '%s'\n", a, b);
88                        bool match = false;
89                        char *a2 = a;
90                        do
91                        {
92                                if (MatchName(a2, b, level+1)) { a = a2; match = true; break; }
93                        } while (*a2++);
94                        if (!match) return false;
95                        //for (int i=0; i<level; i++) printf("  "); printf("matched a='%s' b='%s'\n", a, b);
96                }
97                //for (int i=0; i<level; i++) printf("  "); printf("a=%s b=%s\n", a, b);
98                if (!*a && !*b) return true;
99                if (*a && !*b) return false;
100                if (!*a && *b) return false;
101                if (*b != '?' && *a != *b) return false;
102                a++; b++;
103        }
104}
105
106/*
107 * ExtractDirectory
108 * filerootdir can be 0 for just listing files
109 */
110void ExtractDirectory(const char *prefix, unsigned int dir_id)
111{
112        char strbuf[MAXPATHLEN];
113        unsigned int save_filepos = ftell(fNDS);
114
115        fseek(fNDS, header.fnt_offset + 8*(dir_id & 0xFFF), SEEK_SET);
116        unsigned_int entry_start;       // reference location of entry name
117        fread(&entry_start, 1, sizeof(entry_start), fNDS);
118        unsigned_short top_file_id;     // file ID of top entry
119        fread(&top_file_id, 1, sizeof(top_file_id), fNDS);
120        unsigned_short parent_id;       // ID of parent directory or directory count (root)
121        fread(&parent_id, 1, sizeof(parent_id), fNDS);
122
123        fseek(fNDS, header.fnt_offset + entry_start, SEEK_SET);
124
125        // print directory name
126        //printf("%04X ", dir_id);
127        if (!filerootdir || verbose)
128        {
129                printf("%s\n", prefix);
130        }
131
132        for (unsigned int file_id=top_file_id; ; file_id++)
133        {
134                unsigned char entry_type_name_length;
135                fread(&entry_type_name_length, 1, sizeof(entry_type_name_length), fNDS);
136                unsigned int name_length = entry_type_name_length & 127;
137                bool entry_type_directory = (entry_type_name_length & 128) ? true : false;
138                if (name_length == 0) break;
139
140                char entry_name[128];
141                memset(entry_name, 0, 128);
142                fread(entry_name, 1, entry_type_name_length & 127, fNDS);
143                if (entry_type_directory)
144                {
145                        unsigned_short dir_id;
146                        fread(&dir_id, 1, sizeof(dir_id), fNDS);
147
148                        if (filerootdir)
149                        {
150                                strcpy(strbuf, filerootdir);
151                                strcat(strbuf, prefix);
152                                strcat(strbuf, entry_name);
153                                MkDir(strbuf);
154                        }
155
156                        strcpy(strbuf, prefix);
157                        strcat(strbuf, entry_name);
158                        strcat(strbuf, "/");
159                        ExtractDirectory(strbuf, dir_id);
160                }
161                else
162                {
163                        if (1)
164                        {
165                                bool match = (filemask_num == 0);
166                                for (int i=0; i<filemask_num; i++)
167                                {
168                                        //printf("%s %s\n", entry_name, filemasks[i]);
169                                        if (MatchName(entry_name, filemasks[i])) { match = true; break; }
170                                }
171
172                                //if (!directorycreated)
173                                //{
174                                //}
175
176                                //printf("%d\n", match);
177
178                                if (match) ExtractFile(filerootdir, prefix, entry_name, file_id);
179                        }
180                }
181        }
182
183        fseek(fNDS, save_filepos, SEEK_SET);
184}
185
186/*
187 * ExtractFiles
188 */
189void ExtractFiles(char *ndsfilename)
190{
191//printf("%d\n", MatchName("hello", "h*el*lo")); exit(0);               // TEST
192        fNDS = fopen(ndsfilename, "rb");
193        if (!fNDS) { fprintf(stderr, "Cannot open file '%s'.\n", ndsfilename); exit(1); }
194        fread(&header, 512, 1, fNDS);
195
196        if (filerootdir)
197        {
198                MkDir(filerootdir);
199        }
200
201        ExtractDirectory("/", 0xF000);          // list or extract
202
203        fclose(fNDS);
204}
205
206/*
207 * ExtractOverlayFiles2
208 */
209 void ExtractOverlayFiles2(unsigned int overlay_offset, unsigned int overlay_size)
210 {
211        OverlayEntry overlayEntry;
212
213        if (overlay_size)
214        {
215                fseek(fNDS, overlay_offset, SEEK_SET);
216                for (unsigned int i=0; i<overlay_size; i+=sizeof(OverlayEntry))
217                {
218                        fread(&overlayEntry, 1, sizeof(overlayEntry), fNDS);
219                        char s[32]; sprintf(s, OVERLAY_FMT, overlayEntry.file_id);
220                        ExtractFile(overlaydir, "/", s, overlayEntry.file_id);
221                }
222        }
223}
224
225/*
226 * ExtractOverlayFiles
227 */
228void ExtractOverlayFiles()
229{
230        fNDS = fopen(ndsfilename, "rb");
231        if (!fNDS) { fprintf(stderr, "Cannot open file '%s'.\n", ndsfilename); exit(1); }
232        fread(&header, 512, 1, fNDS);
233
234        if (overlaydir)
235        {
236                MkDir(overlaydir);
237        }
238
239        ExtractOverlayFiles2(header.arm9_overlay_offset, header.arm9_overlay_size);
240        ExtractOverlayFiles2(header.arm7_overlay_offset, header.arm7_overlay_size);
241
242        fclose(fNDS);
243}
244
245/*
246 * Extract
247 */
248void Extract(char *outfilename, bool indirect_offset, unsigned int offset, bool indirect_size, unsigned size, bool with_footer)
249{
250        fNDS = fopen(ndsfilename, "rb");
251        if (!fNDS) { fprintf(stderr, "Cannot open file '%s'.\n", ndsfilename); exit(1); }
252        fread(&header, 512, 1, fNDS);
253
254        if (indirect_offset) offset = *((unsigned int *)&header + offset/4);
255        if (indirect_size) size = *((unsigned int *)&header + size/4);
256
257        fseek(fNDS, offset, SEEK_SET);
258
259        FILE *fo = fopen(outfilename, "wb");
260        if (!fo) { fprintf(stderr, "Cannot create file '%s'.\n", outfilename); exit(1); }
261
262        unsigned char copybuf[1024];
263        while (size > 0)
264        {
265                unsigned int size2 = (size >= sizeof(copybuf)) ? sizeof(copybuf) : size;
266                fread(copybuf, 1, size2, fNDS);
267                fwrite(copybuf, 1, size2, fo);
268                size -= size2;
269        }
270
271        if (with_footer)
272        {
273                unsigned_int nitrocode;
274                fread(&nitrocode, sizeof(nitrocode), 1, fNDS);
275                if (nitrocode == 0xDEC00621)
276                {
277                        // 0x2106C0DE, version info, reserved?
278                        for (int i=0; i<3; i++)         // write additional 3 words
279                        {
280                                fwrite(&nitrocode, sizeof(nitrocode), 1, fo);
281                                fread(&nitrocode, sizeof(nitrocode), 1, fNDS);  // next field
282                        }
283                }
284        }
285
286        fclose(fo);
287        fclose(fNDS);
288}
Note: See TracBrowser for help on using the repository browser.