rendered paste body// pack-u8.c by Superken7 - internal beta version.// BETA VERSION. Does NOT support packing subdirectories// Based on magicus' parse-u8.c // Sorry, i was also too lazy to get all the functions needed// from seghers tools.c , so seghers tools' source code is required. #define _GNU_SOURCE #include <sys/stat.h>#include <sys/types.h>#include <dirent.h> #include <string.h>#include <stdlib.h>#include <stdio.h>#include <unistd.h> #include "tools.h" #define round_up(x,n) (-(-(x) & -(n)))#define round64(x) round_up(x,0x40)#define round32(x) round_up(x,0x20)#define round16(x) round_up(x,0x10)#define ERROR(s) do { fprintf(stderr, s "\n"); exit(1); } while (0) static FILE *fp; static char *outdir; typedef struct { u16 type; u16 name_offset; u32 data_offset; // == absolut offset frn U.8- headerns brjan u32 size; // last included file num for directories} U8_node; typedef struct{ u32 tag; // 0x55AA382D "U.8-" u32 rootnode_offset; // offset to root_node, always 0x20. u32 header_size; // size of header from root_node to end of string table. u32 data_offset; // offset to data -- this is rootnode_offset + header_size, aligned to 0x40. u8 zeroes[16];} U8_archive_header;typedef char U8_string[256];int write_file(char *path, FILE *fout){ u8 buffer[4096]; u32 size, tot_size; FILE *fin; fin = fopen(path, "rb"); if (fin == NULL) return 0; tot_size = 0; while(!feof(fin)) { size = fread((u8*)buffer, 1, 4096, fin); tot_size += size; fwrite((u8*)buffer, size, 1, fout); } while(tot_size - round32(tot_size) != 0) { fputc(0, fout); tot_size++; } fclose(fin); return 1;}u32 get_num_entries(DIR *d){ u32 num; struct dirent *dir; num = 0; rewinddir(d); while((dir=readdir(d)) != NULL) { // printf("#%d %s\n",num+1, dir->d_name); num++; } rewinddir(d); return num;}int build_strings(U8_string *strings, DIR *dir){ int i = 0; struct stat st; struct dirent *d; u16 name_off = 3; // 0x00 + "." + 0x00 u32 size; rewinddir(dir); while((d=readdir(dir)) != NULL) { if (!strcmp(d->d_name, ".") || (!strcmp(d->d_name, ".."))) continue; strcpy(strings[i], (char*)(d->d_name)); stat(d->d_name, &st); //printf("#%d %s\n",i+1,d->d_name); fflush(stdout); name_off += strlen(strings[i]) +1; i++; } return name_off;}int build_nodes(U8_node *nodes, U8_string *strings, DIR *dir, u32 strings_size){ int i = 0; int j; struct stat st; struct dirent *d; u16 name_off = 3; // 0x00 + "." + 0x00 u32 data_off; u32 nodes_size; u32 size; u32 filedata_off; rewinddir(dir); while((d=readdir(dir)) != NULL) { if (!strcmp(d->d_name, ".") || (!strcmp(d->d_name, ".."))) continue; stat(d->d_name, &st); if (S_ISDIR(st.st_mode)) { nodes[i].type = be16("\x01\x00");// printf("DIR!\n"); } else { nodes[i].type = be16("\x00\x00");// printf("FILE!\n"); } size = st.st_size; nodes[i].size = size; data_off = round32(data_off + size); nodes[i].name_offset = be16((u8*)&name_off); name_off += strlen(strings[i]) +1; i++; } filedata_off = 0; nodes_size = (i+2)*sizeof(U8_node); /* (root node + ./ node + num_files) *size(node) */ for(j=0; j<i; j++) { /* strtable + nodes_size + header = abs. offset */ nodes[j].data_offset = filedata_off + round32(nodes_size + 0x20 + strings_size); nodes[j].data_offset = be32((u8*)&(nodes[j].data_offset)); filedata_off += round32(nodes[j].size); nodes[j].size = be32((u8*)&(nodes[j].size)); } return ;} int do_U8_archive(FILE *f, char *path){ U8_archive_header header; U8_node root_node; U8_node *nodes; U8_string *strings; u32 num_nodes; u32 root_size; u32 data_offset; u16 strtable_size; u16 i; DIR *d; d = opendir(path); if (d == NULL) return 0; chdir(path); header.tag = 0x55AA382D; header.tag = be32((u8*)&(header.tag)); header.rootnode_offset = (u32)0x20;// printf("rootnode offset "); hexdump((u8*)&header.rootnode_offset, 4); header.rootnode_offset = be32((u8*)&(header.rootnode_offset)); memset(header.zeroes, 0, 0x10); num_nodes = get_num_entries(d); //printf("%d entries\n",num_nodes); root_size = num_nodes +2; // rootnode and ./ root_node.size = be32((u8*)&num_nodes); root_node.type = 0x0100; root_node.type = be16((u8*)&(root_node.type)); root_node.name_offset = 0; root_node.data_offset = 0; num_nodes -= 2; printf("%d files found!\n", num_nodes); strings = (U8_string *)malloc(sizeof(U8_string) * num_nodes); if (strings == NULL) { fprintf(stderr,"memory error :/\n"); return 0; } nodes = (U8_node *) malloc(sizeof(U8_node) * num_nodes); if (nodes == NULL) { fprintf(stderr,"memory error :/\n"); return 0; } strtable_size = build_strings(strings, d);// printf("stringtable %08x\n",strtable_size); build_nodes(nodes, strings, d, strtable_size); header.header_size = 2*sizeof(U8_node) + num_nodes*sizeof(U8_node) + strtable_size;// printf("rootnode offset "); fflush(stdout);hexdump((u8*)&header.rootnode_offset, 4); header.data_offset = round32(0x20 + header.header_size); data_offset = header.data_offset; //save in host byte-order for later header.header_size = be32((u8*)&(header.header_size));// printf("header size "); fflush(stdout);hexdump((u8*)&header.header_size,4); header.data_offset = be32((u8*)&(header.data_offset));// printf("data offset "); fflush(stdout);hexdump((u8*)&header.data_offset,4); fwrite((u8*)&header, sizeof(U8_archive_header), 1, f); fwrite((u8*)&root_node, sizeof(U8_node), 1, f); /* write ./ directory , * just differs from root node in name offset * */ root_node.name_offset = 0x0001; root_node.name_offset = be16((u8*)&(root_node.name_offset)); fwrite((u8*)&root_node, sizeof(U8_node), 1, f); /* write nodes */ for(i=0; i<num_nodes; i++) { /* meh, inefficient, but who cares.. */ fwrite((u8*)&(nodes[i]), sizeof(U8_node), 1, f); } /* write string table */ fwrite((u8*)"\x00\x2e\x00", 3, 1, f); /* root node + ./ node */ for(i=0; i<num_nodes; i++) { printf("#%d %s\n",i+1,strings[i]); fwrite((u8*)strings[i], strlen(strings[i])+1, 1, f); } /* align to 0x20 */ for (i=0; i<(data_offset - strtable_size - (num_nodes+2)*sizeof(U8_node) -sizeof(header)); i++) fputc(0, f); /* write files */ for (i=0; i<num_nodes; i++) { write_file(strings[i], f); } chdir(".."); free(nodes); closedir(d); return 1;} int main(int argc, char **argv){ if (argc != 3) return 0; printf("U8 packer: \"internal\" beta version by Superken7.\n\n"); fp = fopen(argv[1], "wb"); if (fp == NULL) { fprintf(stderr, "Can not open file %s\n",argv[1]); return 0; } do_U8_archive(fp, argv[2]); fclose(fp); return 0;}