Line 1: |
Line 1: |
| '''Put this file in the same directory as a compiled version of [[Segher's Wii.git]] tools, since it depends on them.''' | | '''Put this file in the same directory as a compiled version of [[Segher's Wii.git]] tools, since it depends on them.''' |
− |
| |
− | : Sorry for the beta status, it's 2 am and I need to get some sleep ;-) but I thought it was better I released what I've done so far. Feel free to improve it. [[User:Magicus|Magicus]] 17:00, 1 March 2008 (PST)
| |
| | | |
| <pre> | | <pre> |
Line 15: |
Line 13: |
| | | |
| // Version 0.5 Beta version, just lists contents, doesn't yet extract files. | | // Version 0.5 Beta version, just lists contents, doesn't yet extract files. |
| + | // Version 1.0 Now extract files and re-create directory structure. |
| | | |
| + | #define _GNU_SOURCE |
| | | |
| #include <sys/stat.h> | | #include <sys/stat.h> |
Line 37: |
Line 37: |
| static FILE *fp; | | static FILE *fp; |
| | | |
− | static char *outdir = "OUTDIR"; | + | static char *outdir; |
| | | |
| typedef struct | | typedef struct |
Line 56: |
Line 56: |
| } U8_archive_header; | | } U8_archive_header; |
| | | |
− | /*
| + | static void write_file(void* data, size_t size, char* name) |
− | static void write_part(void* data, size_t size, char* name) | |
| { | | { |
| FILE *out; | | FILE *out; |
− | char filename[128];
| |
| | | |
− | snprintf(filename, sizeof(filename), "%s_%s.bin", gamename, name);
| + | out = fopen(name, "wb"); |
− | filename[127] = '\0';
| |
− | out = fopen(filename, "wb"); | |
| fwrite(data, 1, size, out); | | fwrite(data, 1, size, out); |
| fclose(out); | | fclose(out); |
| } | | } |
− | */
| |
| | | |
| | | |
Line 82: |
Line 77: |
| unsigned int i; | | unsigned int i; |
| u32 data_offset; | | u32 data_offset; |
| + | u32 current_offset; |
| + | u16 dir_stack[16]; |
| + | int dir_index = 0; |
| | | |
| fread(&header, 1, sizeof header, fp); | | fread(&header, 1, sizeof header, fp); |
Line 97: |
Line 95: |
| | | |
| data_offset = be32((u8*) &header.data_offset); | | data_offset = be32((u8*) &header.data_offset); |
− | rest_size = data_offset - sizeof(header) - num_nodes*sizeof(U8_node); | + | rest_size = data_offset - sizeof(header) - (num_nodes+1)*sizeof(U8_node); |
| | | |
| string_table = malloc(rest_size); | | string_table = malloc(rest_size); |
| fread(string_table, 1, rest_size, fp); | | fread(string_table, 1, rest_size, fp); |
− |
| + | current_offset = data_offset; |
| + | |
| for (i = 0; i < num_nodes; i++) { | | for (i = 0; i < num_nodes; i++) { |
| U8_node* node = &nodes[i]; | | U8_node* node = &nodes[i]; |
| u16 type = be16((u8*)&node->type); | | u16 type = be16((u8*)&node->type); |
| u16 name_offset = be16((u8*)&node->name_offset); | | u16 name_offset = be16((u8*)&node->name_offset); |
− | u32 data_offset = be32((u8*)&node->data_offset); | + | u32 my_data_offset = be32((u8*)&node->data_offset); |
| u32 size = be32((u8*)&node->size); | | u32 size = be32((u8*)&node->size); |
| char* name = (char*) &string_table[name_offset]; | | char* name = (char*) &string_table[name_offset]; |
− | char* premarker; | + | u8* file_data; |
− | char* postmarker;
| |
| | | |
| if (type == 0x0100) { | | if (type == 0x0100) { |
− | premarker = ""; | + | // Directory |
− | postmarker = "/"; | + | mkdir(name, 0777); |
| + | chdir(name); |
| + | dir_stack[++dir_index] = size; |
| + | printf("%*s%s/\n", dir_index, "", name); |
| } else { | | } else { |
− | premarker = " "; | + | // Normal file |
− | postmarker = ""; | + | u8 padding[32]; |
| + | |
| + | if (type != 0x0000) { |
| + | ERROR("Unknown type"); |
| + | } |
| + | |
| + | if (current_offset < my_data_offset) { |
| + | int diff = my_data_offset - current_offset; |
| + | |
| + | if (diff > 32) { |
| + | ERROR("Archive inconsistency, too much padding"); |
| + | } |
| + | fread(padding, 1, diff, fp); |
| + | current_offset += diff; |
| + | } |
| + | |
| + | file_data = malloc(size); |
| + | fread(file_data, 1, size, fp); |
| + | write_file(file_data, size, name); |
| + | current_offset += size; |
| + | printf("%*s %s (%d bytes)\n", dir_index, "", name, size); |
| + | } |
| + | |
| + | while (dir_stack[dir_index] == i+2 && dir_index > 0) { |
| + | chdir(".."); |
| + | dir_index--; |
| } | | } |
− |
| |
− | printf("%s%s%s (%d) offset: %x\n", premarker, name, postmarker, size, data_offset);
| |
| } | | } |
| } | | } |
Line 126: |
Line 150: |
| int main(int argc, char **argv) | | int main(int argc, char **argv) |
| { | | { |
| + | char outdir_name[128]; |
| + | |
| if (argc == 3) { | | if (argc == 3) { |
| outdir = argv[2]; | | outdir = argv[2]; |
| } else if (argc != 2) { | | } else if (argc != 2) { |
| ERROR("Usage: parse-u8 <file> [<outdir>]"); | | ERROR("Usage: parse-u8 <file> [<outdir>]"); |
| + | } else { |
| + | |
| + | snprintf(outdir_name, sizeof(outdir_name), "%s.unpacked", basename(argv[1])); |
| + | outdir_name[127] = '\0'; |
| + | outdir = outdir_name; |
| } | | } |
| | | |
| + | printf("Extracting files to %s.\n", outdir); |
| fp = fopen(argv[1], "rb"); | | fp = fopen(argv[1], "rb"); |
| | | |
− | // mkdir(outdir, 0777);
| + | mkdir(outdir, 0777); |
− | // chdir(outdir);
| + | chdir(outdir); |
| | | |
| do_U8_archive(); | | do_U8_archive(); |
Line 143: |
Line 175: |
| return 0; | | return 0; |
| } | | } |
− |
| |
| </pre> | | </pre> |