source: rtems/c/src/lib/libbsp/arm/nds/tools/ndstool/source/ndscreate.cpp @ 9a12c7e5

4.104.11
Last change on this file since 9a12c7e5 was 9a12c7e5, checked in by Joel Sherrill <joel.sherrill@…>, on May 4, 2009 at 2:04:42 AM

2009-05-03 Joel Sherrill <joel.sherrill@…>

  • ndstool/include/banner.h, ndstool/include/header.h, ndstool/include/ndstree.h, ndstool/source/banner.cpp, ndstool/source/header.cpp, ndstool/source/ndscreate.cpp, ndstool/source/ndstool.cpp, ndstool/source/passme.cpp: Remove warnings for deprecated character conversions.
  • Property mode set to 100644
File size: 17.9 KB
Line 
1#include <time.h>
2#include <ndstool.h>
3#include "logo.h"
4#include "raster.h"
5#include "banner.h"
6#include "overlay.h"
7#include "loadme.h"
8#include "ndstree.h"
9
10unsigned int arm9_align = 0x1FF;
11unsigned int arm7_align = 0x1FF;
12unsigned int fnt_align = 0x1FF;         // 0x3 0x1FF
13unsigned int fat_align = 0x1FF;         // 0x3 0x1FF
14unsigned int banner_align = 0x1FF;
15unsigned int file_align = 0x1FF;        // 0x3 0x1FF
16
17unsigned int overlay_files = 0;
18
19unsigned char romcontrol[] = { 0x00,0x60,0x58,0x00,0xF8,0x08,0x18,0x00 };
20
21const unsigned char nintendo_logo[] =
22{
23        0x24,0xFF,0xAE,0x51,0x69,0x9A,0xA2,0x21,0x3D,0x84,0x82,0x0A,0x84,0xE4,0x09,0xAD,
24        0x11,0x24,0x8B,0x98,0xC0,0x81,0x7F,0x21,0xA3,0x52,0xBE,0x19,0x93,0x09,0xCE,0x20,
25        0x10,0x46,0x4A,0x4A,0xF8,0x27,0x31,0xEC,0x58,0xC7,0xE8,0x33,0x82,0xE3,0xCE,0xBF,
26        0x85,0xF4,0xDF,0x94,0xCE,0x4B,0x09,0xC1,0x94,0x56,0x8A,0xC0,0x13,0x72,0xA7,0xFC,
27        0x9F,0x84,0x4D,0x73,0xA3,0xCA,0x9A,0x61,0x58,0x97,0xA3,0x27,0xFC,0x03,0x98,0x76,
28        0x23,0x1D,0xC7,0x61,0x03,0x04,0xAE,0x56,0xBF,0x38,0x84,0x00,0x40,0xA7,0x0E,0xFD,
29        0xFF,0x52,0xFE,0x03,0x6F,0x95,0x30,0xF1,0x97,0xFB,0xC0,0x85,0x60,0xD6,0x80,0x25,
30        0xA9,0x63,0xBE,0x03,0x01,0x4E,0x38,0xE2,0xF9,0xA2,0x34,0xFF,0xBB,0x3E,0x03,0x44,
31        0x78,0x00,0x90,0xCB,0x88,0x11,0x3A,0x94,0x65,0xC0,0x7C,0x63,0x87,0xF0,0x3C,0xAF,
32        0xD6,0x25,0xE4,0x8B,0x38,0x0A,0xAC,0x72,0x21,0xD4,0xF8,0x07,
33};
34
35/*
36 * HasElfExtension
37 */
38bool HasElfExtension(char *filename)
39{
40        char *p = strrchr(filename, '.');
41        if (!p) return false;
42        return (strcmp(p, ".elf") == 0);
43}
44
45/*
46 * CopyFromBin
47 */
48int CopyFromBin(char *binFilename, unsigned int *size = 0, unsigned int *size_without_footer = 0)
49{
50        FILE *fi = fopen(binFilename, "rb");
51        if (!fi) { fprintf(stderr, "Cannot open file '%s'.\n", binFilename); exit(1); }
52        unsigned int _size = 0;
53        while (1)
54        {
55                unsigned char buffer[1024];
56                int bytesread = fread(buffer, 1, sizeof(buffer), fi);
57                if (bytesread <= 0) break;
58                fwrite(buffer, 1, bytesread, fNDS);
59                _size += bytesread;
60        }
61        if (size) *size = _size;
62
63        // check footer
64        if (size_without_footer)
65        {
66                fseek(fi, _size - 3*4, SEEK_SET);
67                unsigned_int nitrocode;
68                fread(&nitrocode, sizeof(nitrocode), 1, fi);
69                if (nitrocode == 0xDEC00621)
70                        *size_without_footer = _size - 3*4;
71                else
72                        *size_without_footer = _size;
73        }
74
75        fclose(fi);
76        return 0;
77}
78
79/*
80 * CopyFromElf
81 */
82#if 0
83int CopyFromElf(char *elfFilename, unsigned int *entry, unsigned int *ram_address, unsigned int *size)
84{
85        int fd = open(elfFilename, O_RDONLY);
86        if (fd < 0) { fprintf(stderr, "Cannot open file '%s'.\n", elfFilename); exit(1); }
87        if (elf_version(EV_CURRENT) == EV_NONE) { fprintf(stderr, "libelf out of date!\n"); exit(1); }
88        Elf *elf;
89        if ((elf = elf_begin(fd, ELF_C_READ, 0)) == 0) { fprintf(stderr, "Cannot open ELF file!\n"); exit(1); }
90        Elf32_Ehdr *ehdr;
91        if ((ehdr = elf32_getehdr(elf)) == 0) { fprintf(stderr, "Cannot read ELF header!\n"); exit(1); }
92        if (ehdr->e_machine != EM_ARM) { fprintf(stderr, "Not an ARM ELF file!\n"); exit(1); }
93
94        *entry = ehdr->e_entry;
95        *size = 0;
96        *ram_address = 0;
97//      printf("entry = 0x%X\n", ehdr->e_entry);
98
99    Elf_Scn *scn = elf_getscn(elf, 0);
100        Elf32_Shdr *shdr = elf32_getshdr(scn);
101    while (shdr)
102    {
103                if (shdr->sh_flags & SHF_ALLOC)
104                {
105/*                      char *name;
106                        if (!(name = elf_strptr(elf, ehdr->e_shstrndx, shdr->sh_name))) name = "???";
107                printf("%s\n", name);*/
108
109                        if (!*ram_address) *ram_address = shdr->sh_addr;                // use first address (assume it's .text)
110
111// don't mind the garbage here
112
113//                      printf("sh_addr=0x%X sh_offset=0x%X sh_size=0x%X sh_link=%u sh_entsize=%u sh_addralign=%u\n", shdr->sh_addr, shdr->sh_offset, shdr->sh_size, shdr->sh_link, shdr->sh_entsize, shdr->sh_addralign);
114                        //    Elf32_Word                sh_name;
115                        //    Elf32_Word                sh_type;
116                        //    Elf32_Word                sh_flags;
117                        //    Elf32_Addr                sh_addr;
118                        //    Elf32_Off         sh_offset;
119                        //    Elf32_Word                sh_size;
120                        //    Elf32_Word                sh_link;
121                        //    Elf32_Word                sh_info;
122                        //    Elf32_Word                sh_addralign;
123                        //    Elf32_Word                sh_entsize;
124
125                        Elf_Data *data;
126                        if ((data = elf_getdata(scn, NULL)))
127                        {
128                        /*for (int i=0; i<data->d_size; i++)
129                        {
130                                        printf("%02X ", ((unsigned char *)data->d_buf)[i]);
131                        }
132                        printf("\n");*/
133                        fwrite(data->d_buf, 1, data->d_size, fNDS);
134                                *size += data->d_size;
135                        }
136                }
137
138                scn = elf_nextscn(elf, scn);
139                shdr = elf32_getshdr(scn);
140    }
141
142        elf_end(elf);
143
144        return 0;
145}
146#endif
147
148/*
149 * AddFile
150 */
151void AddFile(char *rootdir, const char *prefix, const char *entry_name, unsigned int file_id)
152{
153        // make filename
154        char strbuf[MAXPATHLEN];
155        strcpy(strbuf, rootdir);
156        strcat(strbuf, prefix);
157        strcat(strbuf, entry_name);
158
159        //unsigned int file_end = ftell(fNDS);
160
161        file_top = (file_top + file_align) &~ file_align;
162        fseek(fNDS, file_top, SEEK_SET);
163
164        FILE *fi = fopen(strbuf, "rb");
165        if (!fi) { fprintf(stderr, "Cannot open file '%s'.\n", strbuf); exit(1); }
166        fseek(fi, 0, SEEK_END);
167        unsigned int size = ftell(fi);
168        unsigned int file_bottom = file_top + size;
169        fseek(fi, 0, SEEK_SET);
170
171        // print
172        if (verbose)
173        {
174                printf("%5u 0x%08X 0x%08X %9u %s%s\n", file_id, file_top, file_bottom, size, prefix, entry_name);
175        }
176
177        // write data
178        unsigned int sizeof_copybuf = 256*1024;
179        unsigned char *copybuf = new unsigned char [sizeof_copybuf];
180        while (size > 0)
181        {
182                unsigned int size2 = (size >= sizeof_copybuf) ? sizeof_copybuf : size;
183                fread(copybuf, 1, size2, fi);
184                fwrite(copybuf, 1, size2, fNDS);
185                size -= size2;
186        }
187        delete [] copybuf;
188        fclose(fi);
189        if ((unsigned int)ftell(fNDS) > file_end) file_end = ftell(fNDS);
190
191        // write fat
192        fseek(fNDS, header.fat_offset + 8*file_id, SEEK_SET);
193        unsigned_int top = file_top;
194        fwrite(&top, 1, sizeof(top), fNDS);
195        unsigned_int bottom = file_bottom;
196        fwrite(&bottom, 1, sizeof(bottom), fNDS);
197
198        file_top = file_bottom;
199}
200
201/*
202 * AddDirectory
203 * Walks the tree and adds files to NDS
204 */
205void AddDirectory(TreeNode *node, const char *prefix, unsigned int this_dir_id, unsigned int _parent_id)
206{
207        // skip dummy node
208        node = node->next;
209
210        if (verbose) printf("%s\n", prefix);
211
212        // write directory info
213        fseek(fNDS, header.fnt_offset + 8*(this_dir_id & 0xFFF), SEEK_SET);
214        unsigned_int entry_start = _entry_start;        // reference location of entry name
215        fwrite(&entry_start, 1, sizeof(entry_start), fNDS);
216        unsigned int _top_file_id = free_file_id;
217        unsigned_short top_file_id = _top_file_id;      // file ID of top entry
218        fwrite(&top_file_id, 1, sizeof(top_file_id), fNDS);
219        unsigned_short parent_id = _parent_id;  // ID of parent directory or directory count (root)
220        fwrite(&parent_id, 1, sizeof(parent_id), fNDS);
221
222        //printf("dir %X file_id %u +\n", this_dir_id, (int)top_file_id);
223
224        // directory entrynames
225        {
226                // start of directory entrynames
227                fseek(fNDS, header.fnt_offset + _entry_start, SEEK_SET);
228
229                // write filenames
230                for (TreeNode *t=node; t; t=t->next)
231                {
232                        if (!t->directory)
233                        {
234                                int namelen = strlen(t->name);
235                                fputc(t->directory ? namelen | 128 : namelen, fNDS); _entry_start += 1;
236                                fwrite(t->name, 1, namelen, fNDS); _entry_start += namelen;
237
238                                //printf("[ %s -> %u ]\n", t->name, free_file_id);
239
240                                free_file_id++;
241                        }
242                }
243
244                // write directorynames
245                for (TreeNode *t=node; t; t=t->next)
246                {
247                        if (t->directory)
248                        {
249                                //printf("*entry %s\n", t->name);
250
251                                int namelen = strlen(t->name);
252                                fputc(t->directory ? namelen | 128 : namelen, fNDS); _entry_start += 1;
253                                fwrite(t->name, 1, namelen, fNDS); _entry_start += namelen;
254
255                                //printf("[ %s -> %X ]\n", t->name, t->dir_id);
256
257                                unsigned_short _dir_id_tmp = t->dir_id;
258                                fwrite(&_dir_id_tmp, 1, sizeof(_dir_id_tmp), fNDS);
259                                _entry_start += sizeof(_dir_id_tmp);
260                        }
261                }
262
263                fputc(0, fNDS); _entry_start += 1;      // end of directory entrynames
264        }
265
266        // add files
267        unsigned int local_file_id = _top_file_id;
268        for (TreeNode *t=node; t; t=t->next)
269        {
270                //printf("*2* %s\n", t->name);
271
272                if (!t->directory)
273                {
274                        AddFile(filerootdir, prefix, t->name, local_file_id++);
275                }
276        }
277
278        // add subdirectories
279        for (TreeNode *t=node; t; t=t->next)
280        {
281                //printf("*2* %s\n", t->name);
282
283                if (t->directory)
284                {
285                        char strbuf[MAXPATHLEN];
286                        strcpy(strbuf, prefix);
287                        strcat(strbuf, t->name);
288                        strcat(strbuf, "/");
289                        AddDirectory(t->directory, strbuf, t->dir_id, this_dir_id);
290                }
291        }
292}
293
294/*
295 * Create
296 */
297void Create()
298{
299        fNDS = fopen(ndsfilename, "wb");
300        if (!fNDS) { fprintf(stderr, "Cannot open file '%s'.\n", ndsfilename); exit(1); }
301
302        bool bSecureSyscalls = false;
303        char *headerfilename = (headerfilename_or_size && (strtoul(headerfilename_or_size,0,0) == 0)) ? headerfilename_or_size : 0;
304        u32 headersize = headerfilename_or_size ? strtoul(headerfilename_or_size,0,0) : 0x200;
305
306        // initial header data
307        if (headerfilename)
308        {
309                // header template
310                FILE *fi = fopen(headerfilename, "rb");
311                if (!fi) { fprintf(stderr, "Cannot open file '%s'.\n", headerfilename); exit(1); }
312                fread(&header, 1, 0x200, fi);
313                fclose(fi);
314               
315                if ((header.arm9_ram_address + 0x800 == header.arm9_entry_address) || (header.rom_header_size > 0x200))
316                {
317                        bSecureSyscalls = true;
318                }
319        }
320        else    // set header default values
321        {
322                // clear header
323                memset(&header, 0, 0x200);
324                memcpy(header.gamecode, "####", 4);
325
326                if ((arm9RamAddress + 0x800 == arm9Entry) || (headersize > 0x200))
327                {
328                        bSecureSyscalls = true;
329                }
330                else
331                {
332                        header.reserved2 = 0x04;                // autostart
333                        *(unsigned_int *)(((unsigned char *)&header) + 0x0) = 0xEA00002E;               // for PassMe's that start @ 0x08000000
334                }
335                *(unsigned_int *)(((unsigned char *)&header) + 0x60) = 1<<22 | latency2<<16 | 1<<14 | 1<<13 | latency1; // ROM control info 1
336                *(unsigned_int *)(((unsigned char *)&header) + 0x64) = 1<<29 | latency2<<16 | latency1; // ROM control info 2
337                *(unsigned_short *)(((unsigned char *)&header) + 0x6E) = 0x051E;        // ROM control info 3
338        }
339        if (headersize) header.rom_header_size = headersize;
340        if (header.rom_header_size == 0) header.rom_header_size = bSecureSyscalls ? 0x4000 : 0x200;
341
342        // load a logo
343        if (logofilename)
344        {
345                char *p = strrchr(logofilename, '.');
346                if (!strcmp(p, ".bmp"))
347                {
348                        CRaster raster;
349                        if (raster.LoadBMP(logofilename) < 0) exit(1);
350                        unsigned char white = (raster.palette[0].rgbGreen >= 128) ? 0 : 1;
351                        if (LogoConvert(raster.raster, header.logo, white) < 0) exit(1);
352                }
353                else
354                {
355                        FILE *fi = fopen(logofilename, "rb");
356                        if (!fi) { fprintf(stderr, "Cannot open file '%s'.\n", logofilename); exit(1); }
357                        fread(&header.logo, 1, 156, fi);
358                        fclose(fi);
359                }
360        }
361        else if (bSecureSyscalls)       // use Nintendo logo
362        {
363                memcpy(((unsigned char *)&header) + 0xC0, nintendo_logo, sizeof(nintendo_logo));
364        }
365        else    // add small NDS loader
366        {
367                if (loadme_size != 156) { fprintf(stderr, "loadme size error\n"); exit(1); }
368                memcpy(header.logo, loadme, loadme_size);               // self-contained NDS loader for *Me GBA cartridge boot
369                memcpy(&header.offset_0xA0, "SRAM_V110", 9);            // allow GBA cartridge SRAM backup
370                memcpy(&header.offset_0xAC, "PASS01\x96", 7);           // automatically start with FlashMe, make it look more like a GBA rom
371        }
372
373        // override default title/game/maker codes
374        if (title) strncpy(header.title, title, 12);
375        if (gamecode) strncpy(header.gamecode, gamecode, 4);
376        if (makercode) strncpy((char *)header.makercode, makercode, 2);
377
378        // --------------------------
379
380        fseek(fNDS, header.rom_header_size, SEEK_SET);
381
382        // ARM9 binary
383        if (arm9filename)
384        {
385                header.arm9_rom_offset = (ftell(fNDS) + arm9_align) &~ arm9_align;
386                fseek(fNDS, header.arm9_rom_offset, SEEK_SET);
387
388                unsigned int entry_address = arm9Entry ? arm9Entry : (unsigned int)header.arm9_entry_address;           // template
389                unsigned int ram_address = arm9RamAddress ? arm9RamAddress : (unsigned int)header.arm9_ram_address;             // template
390                if (!ram_address && entry_address) ram_address = entry_address;
391                if (!entry_address && ram_address) entry_address = ram_address;
392                if (!ram_address) { ram_address = entry_address = 0x02000000; }
393
394                // add dummy area for secure syscalls
395                header.arm9_size = 0;
396                if (bSecureSyscalls)
397                {
398                        unsigned_int x;
399                        FILE *fARM9 = fopen(arm9filename, "rb");
400                        if (fARM9)
401                        {
402                                fread(&x, sizeof(x), 1, fARM9);
403                                fclose(fARM9);
404                                if (x != 0xE7FFDEFF)    // not already exist?
405                                {
406                                        x = 0xE7FFDEFF;
407                                        for (int i=0; i<0x800/4; i++) fwrite(&x, sizeof(x), 1, fNDS);
408                                        header.arm9_size = 0x800;
409                                }
410                        }
411                }
412
413                unsigned int size = 0;
414#if 0
415                if (HasElfExtension(arm9filename))
416                        CopyFromElf(arm9filename, &entry_address, &ram_address, &size);
417                else
418#endif
419                        CopyFromBin(arm9filename, 0, &size);
420                header.arm9_entry_address = entry_address;
421                header.arm9_ram_address = ram_address;
422                header.arm9_size = header.arm9_size + ((size + 3) &~ 3);
423        }
424        else
425        {
426                fprintf(stderr, "ARM9 binary file required.\n");
427                exit(1);
428        }
429
430        // ARM9 overlay table
431        if (arm9ovltablefilename)
432        {
433                unsigned_int x1 = 0xDEC00621; fwrite(&x1, sizeof(x1), 1, fNDS);         // 0x2106c0de magic
434                unsigned_int x2 = 0x00000AD8; fwrite(&x2, sizeof(x2), 1, fNDS);         // ???
435                unsigned_int x3 = 0x00000000; fwrite(&x3, sizeof(x3), 1, fNDS);         // ???
436
437                header.arm9_overlay_offset = ftell(fNDS);               // do not align
438                fseek(fNDS, header.arm9_overlay_offset, SEEK_SET);
439                unsigned int size = 0;
440                CopyFromBin(arm9ovltablefilename, &size);
441                header.arm9_overlay_size = size;
442                overlay_files += size / sizeof(OverlayEntry);
443                if (!size) header.arm9_overlay_offset = 0;
444        }
445
446        // COULD BE HERE: ARM9 overlay files, no padding before or between. end is padded with 0xFF's and then followed by ARM7 binary
447        // fseek(fNDS, 1388772, SEEK_CUR);              // test for ASME
448
449        // ARM7 binary
450        header.arm7_rom_offset = (ftell(fNDS) + arm7_align) &~ arm7_align;
451        fseek(fNDS, header.arm7_rom_offset, SEEK_SET);
452
453        char *devkitProPATH;
454        devkitProPATH = getenv("DEVKITPRO");
455
456        #ifdef __WIN32__
457        // convert to standard windows path
458        if ( devkitProPATH && devkitProPATH[0] == '/' ) {
459                devkitProPATH[0] = devkitProPATH[1]; 
460                devkitProPATH[1] = ':';
461        }
462        #endif
463
464        if ( !arm7filename) {
465                char arm7PathName[MAXPATHLEN];
466
467                if (!devkitProPATH) {
468                        fprintf(stderr,"No arm7 specified and DEVKITPRO missing from environment!\n");
469                        exit(1);
470                }
471
472                strcpy(arm7PathName,devkitProPATH);
473                strcat(arm7PathName,"/libnds/basic.arm7");
474                arm7filename = arm7PathName;
475        }
476       
477        unsigned int entry_address = arm7Entry ? arm7Entry : (unsigned int)header.arm7_entry_address;           // template
478        unsigned int ram_address = arm7RamAddress ? arm7RamAddress : (unsigned int)header.arm7_ram_address;             // template
479        if (!ram_address && entry_address) ram_address = entry_address;
480        if (!entry_address && ram_address) entry_address = ram_address;
481        if (!ram_address) { ram_address = entry_address = 0x037f8000; }
482
483        unsigned int size = 0;
484        CopyFromBin(arm7filename, &size);
485
486        header.arm7_entry_address = entry_address;
487        header.arm7_ram_address = ram_address;
488        header.arm7_size = ((size + 3) &~ 3);
489
490        // ARM7 overlay table
491        if (arm7ovltablefilename)
492        {
493                header.arm7_overlay_offset = ftell(fNDS);               // do not align
494                fseek(fNDS, header.arm7_overlay_offset, SEEK_SET);
495                unsigned int size = 0;
496                CopyFromBin(arm7ovltablefilename, &size);
497                header.arm7_overlay_size = size;
498                overlay_files += size / sizeof(OverlayEntry);
499                if (!size) header.arm7_overlay_offset = 0;
500        }
501
502        // COULD BE HERE: probably ARM7 overlay files, just like for ARM9
503        //
504
505        if (overlay_files && !overlaydir)
506        {
507                fprintf(stderr, "Overlay directory required!.\n");
508                exit(1);
509        }
510
511        // filesystem
512        //if (filerootdir || overlaydir)
513        {
514                // read directory structure
515                free_file_id = overlay_files;
516                free_dir_id++;
517                directory_count++;
518                TreeNode *filetree;
519                if (filerootdir)
520                        filetree = ReadDirectory(new TreeNode(), filerootdir);
521                else
522                        filetree = new TreeNode();              // dummy root node 0xF000
523
524                // calculate offsets required for FNT and FAT
525                _entry_start = 8*directory_count;               // names come after directory structs
526                header.fnt_offset = (ftell(fNDS) + fnt_align) &~ fnt_align;
527                header.fnt_size =
528                        _entry_start +          // directory structs
529                        total_name_size +       // total number of name characters for dirs and files
530                        directory_count*4 +     // directory: name length (1), dir id (2), end-character (1)
531                        file_count*1 +          // files: name length (1)
532                        - 3;                            // root directory only has an end-character
533                file_count += overlay_files;            // didn't take overlay files into FNT size, but have to be calculated into FAT size
534                header.fat_offset = (header.fnt_offset + header.fnt_size + fat_align) &~ fat_align;
535                header.fat_size = file_count * 8;               // each entry contains top & bottom offset
536
537                // banner after FNT/FAT
538                if (bannerfilename)
539                {
540                        header.banner_offset = (header.fat_offset + header.fat_size + banner_align) &~ banner_align;
541                        file_top = header.banner_offset + 0x840;
542                        fseek(fNDS, header.banner_offset, SEEK_SET);
543                        if (bannertype == BANNER_IMAGE)
544                        {
545                                IconFromBMP();
546                        }
547                        else
548                        {
549                                CopyFromBin(bannerfilename, 0);
550                        }
551                }
552                else
553                {
554                        file_top = header.fat_offset + header.fat_size;
555                        header.banner_offset = 0;
556                }
557
558                file_end = file_top;    // no file data as yet
559
560                // add (hidden) overlay files
561                for (unsigned int i=0; i<overlay_files; i++)
562                {
563                        char s[32]; sprintf(s, OVERLAY_FMT, i/*free_file_id*/);
564                        AddFile(overlaydir, "/", s, i/*free_file_id*/);
565                        //free_file_id++;               // incremented up to overlay_files
566                }
567
568                // add all other (visible) files
569                AddDirectory(filetree, "/", 0xF000, directory_count);
570                fseek(fNDS, file_end, SEEK_SET);
571
572                if (verbose)
573                {
574                        printf("%u directories.\n", directory_count);
575                        printf("%u normal files.\n", file_count - overlay_files);
576                        printf("%u overlay files.\n", overlay_files);
577                }
578        }
579
580        // --------------------------
581
582        // align file size
583        unsigned int newfilesize = file_end;    //ftell(fNDS);
584        newfilesize = (newfilesize + 3) &~ 3;   // align to 4 bytes
585        header.application_end_offset = newfilesize;
586        fseek(fNDS, newfilesize-1, SEEK_SET); int c = fgetc(fNDS);
587        fseek(fNDS, newfilesize-1, SEEK_SET); fputc((c >= 0) ? c : 0, fNDS);
588
589        // calculate device capacity
590        newfilesize |= newfilesize >> 16; newfilesize |= newfilesize >> 8;
591        newfilesize |= newfilesize >> 4; newfilesize |= newfilesize >> 2;
592        newfilesize |= newfilesize >> 1; newfilesize++;
593        if (newfilesize <= 128*1024) newfilesize = 128*1024;
594        int devcap = -18;
595        unsigned int x = newfilesize;
596        while (x != 0) { x >>= 1; devcap++; }
597        header.devicecap = (devcap < 0) ? 0 : devcap;
598
599        // fix up header CRCs and write header
600        header.logo_crc = CalcLogoCRC(header);
601        header.header_crc = CalcHeaderCRC(header);
602        fseek(fNDS, 0, SEEK_SET);
603        fwrite(&header, 0x200, 1, fNDS);
604
605        fclose(fNDS);
606}
Note: See TracBrowser for help on using the repository browser.