User:Magicus/Magicus's Tools/Parse-u8.c

From WiiBrew
< User:Magicus‎ | Magicus's Tools
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
// parse-u8.c
// Compile with:
// gcc -g -DLARGE_FILES -D_FILE_OFFSET_BITS=64 -Wall -W -O2   -c -o parse-u8.o parse-u8.c
// gcc -g -lcrypto  parse-u8.o tools.o bn.o ec.o   -o parse-u8
// The other files are from segher's git repository, created by his Makefile.

// Copyright 2008 Magicus <magicus@gmail.com>
// Licensed under the terms of the GNU GPL, version 2
// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt

// Version 0.5 Beta version, just lists contents, doesn't yet extract files.


#include <sys/stat.h>
#include <sys/types.h>
       
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

#include "tools.h"

#define ERROR(s) do { fprintf(stderr, s "\n"); exit(1); } while (0)

// FIXME: this should really move to tools.c
u16 be16(u8 *p)
{
	return  (p[0] << 8) | p[1];
}

static FILE *fp;

static char *outdir = "OUTDIR";

typedef struct 
{
  u16 type;
  u16 name_offset;
  u32 data_offset; // == absolut offset från U.8- headerns början
  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;

/*
static void write_part(void* data, size_t size, char* name)
{
	FILE *out;
	char filename[128];

  snprintf(filename, sizeof(filename), "%s_%s.bin", gamename, name);
  filename[127] = '\0';
	out = fopen(filename, "wb");
	fwrite(data, 1, size, out);
	fclose(out);	
}
*/


static void do_U8_archive(void)
{
  U8_archive_header header;
  U8_node root_node;
	u32 tag;
	u32 num_nodes;
	U8_node* nodes;
	u8* string_table;
	size_t rest_size;
	unsigned int i;
	u32 data_offset;

	fread(&header, 1, sizeof header, fp);
	tag = be32((u8*) &header.tag);
	if (tag != 0x55AA382D) {
	  ERROR("No U8 tag");
	}

	fread(&root_node, 1, sizeof(root_node), fp);
	num_nodes = be32((u8*) &root_node.size) - 1;
	printf("Number of files: %d\n", num_nodes);
	
	nodes = malloc(sizeof(U8_node) * (num_nodes));
	fread(nodes, 1, num_nodes * sizeof(U8_node), fp);
	
	data_offset = be32((u8*) &header.data_offset);
	rest_size = data_offset - sizeof(header) - num_nodes*sizeof(U8_node);

	string_table = malloc(rest_size);
	fread(string_table, 1, rest_size, fp);
   
	for (i = 0; i < num_nodes; i++) {
    U8_node* node = &nodes[i];   
    u16 type = be16((u8*)&node->type);
    u16 name_offset = be16((u8*)&node->name_offset);
    u32 data_offset = be32((u8*)&node->data_offset);
    u32 size = be32((u8*)&node->size);
    char* name = (char*) &string_table[name_offset];
    char* premarker;
    char* postmarker;
    
    if (type == 0x0100) {
      premarker = "";
      postmarker = "/";
    } else {
      premarker = " ";
      postmarker = "";
    }
    
    printf("%s%s%s (%d) offset: %x\n", premarker, name, postmarker, size, data_offset);
	}
}

int main(int argc, char **argv)
{
  if (argc == 3) {
    outdir = argv[2];
  } else if (argc != 2) {
    ERROR("Usage: parse-u8 <file> [<outdir>]");
  }

	fp = fopen(argv[1], "rb");

//  mkdir(outdir, 0777);
//  chdir(outdir);
  
  do_U8_archive();

	fclose(fp);

	return 0;
}