Fybertech Forums
September 19, 2017, 07:12:01 PM *
Welcome, Guest. Please login or register.

Login with username, password and session length
News: 06/21/08 - Fybertech: Forgotten History
06/13/08 - Fybertech: The De Novo Project, part 14
06/04/08 - Fybertech: The De Novo Project, part 13
 
   Home   Help Search Calendar Members Login Register  
Pages: [1]
  Print  
Author Topic: Wii U8 Archive Extractor  (Read 7879 times)
FyberOptic
King of Earth
Administrator
*****
Posts: 2520


Oh god what is that?


WWW
« on: August 14, 2008, 03:20:19 PM »

So I wanted to poke around inside the new Strong Bad game, to see what sorts of secrets it might hold in terms of gameplay.  Unfortunately, the PC version's .TTARCH files seem to be encrypted.  So I started with the .WAD to the Wii version instead, and found a utility called WADtool to pull out its contents. 

Checking the resulting .DES files out in a hex editor showed that some of them were archives of some sort.  They seemed similar to the Gamecube's RARC format, but not quite.  The signature ID was wrong too.  So after some more poking around, I stumbled onto a format called U8, and immediately knew that was the one, since the signature dword was the same (0x55AA382D). 

Problem was, the only U8 extractor I saw was some C code, and it needed some extra junk to even be able to compile it.  Forget that.  So I wrote my own, in Perl.  It should probably work on any platform just fine since I didn't use anything crazy.  You pretty much just run "u8extract.pl ARCHIVENAME", and it extracts all the files into a "u8out" subdirectory.

Now I'm stuck with .TTARCH files which I still don't know how to open so far (it's apparently a custom Telltale Games format).  But at least these seem to be unencrypted, unlike the PC version's, so I might have more luck figuring it out.

In any case, here's the script to extract Wii U8 archives, for anyone who might stumble across this and be interested:


Code:
#!/usr/bin/perl
#
# Filename: u8extract.pl
#
# Desc:
# Used to extract files from Wii U8 archives.
# Last updated:
# 08/14/2008
# Usage:
# u8archive.pl archivename
# Note:
# Creates "u8out" directory for output.
#
# - FyberOptic
# http://www.fybertech.com
#


my $u8filename = $ARGV[0];

if (!length($u8filename) || !-e $u8filename) { print "Please specify a U8 archive to extract\n"; exit; }

# Open archive
open(U8FILE, $u8filename);
binmode(u8FILE);

#struct U8_archive_header
#{
#  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];
#};

my $filedata;

# Read archive header
read(U8FILE, $filedata, 16);
my ($header_tag,$rootname_offset,$header_size,$data_offset) = unpack("N N N N",$filedata);

# Check for U8 header tag
if ($header_tag != 0x55AA382D) { print "Invalid U8 archive\n"; exit; }

#print "HEADER: $header_tag $rootname_offset $header_size $data_offset\n";

#Read 16 unknown bytes
read(U8FILE, $filedata, 16);


#struct U8_node
#{
#  u16 type;
#  u16 name_offset;
#  u32 data_offset;
#  u32 size;
#};


# Read first node
read(U8FILE, $filedata, 12);
my ($node_type, $node_nameoffset, $node_dataoffset, $node_size) = unpack("n n N N",$filedata);

#print "FIRST NODE: $node_type, $node_nameoffset, $node_dataoffset, $node_size\n";

# Number of nodes = First node's size
my $totalnodes = $node_size;

# Used to store remaining nodes' hash tables
my @nodes;

# Read nodes (minus one, since we read one already)
for ($n = 0; $n < $totalnodes-1; $n++)
{
read(U8FILE, $filedata, 12);
my ($node_type, $node_nameoffset, $node_dataoffset, $node_size) = unpack("n n N N",$filedata);
#print "NODE $n: $node_type, $node_nameoffset, $node_dataoffset, $node_size\n";

my %currentnode = ('type',$node_type,'nameoffset',$node_nameoffset,'dataoffset',$node_dataoffset, 'size',$node_size);
push @nodes,\%currentnode;
}

#print "STRINGS SIZE: " . ($header_size - tell(U8FILE) + 32) . "\n";

# Read string table
my $stringtabledata;
read(U8FILE, $stringtabledata, $header_size - tell(U8FILE) + 32);

# Split string table into array
my @stringtable = split("\0",$stringtabledata);

# Create directory to store output files
mkdir("u8out");

# Extract files
foreach (0..@nodes-1)
{
my %thisnode = %{$nodes[$_]};
#print "NODE $_: $thisnode{type}, $thisnode{nameoffset}, $thisnode{dataoffset}, $thisnode{size}\n";
#print "FILENAME: $stringtable[$_+1]\n\n";
if ($thisnode{'type'} != 0) { next; }

print "Extracting $stringtable[$_+1]...\n";

my $filebuffer;
seek(U8FILE, $thisnode{'dataoffset'}, 0);
read(U8FILE, $filebuffer, $thisnode{'size'});

open(OUTFILE, "> u8out/$stringtable[$_+1]");
binmode(OUTFILE);
print OUTFILE $filebuffer;
close(OUTFILE);
}

close(U8FILE);
« Last Edit: August 14, 2008, 03:22:43 PM by FyberOptic » Logged
Kingseason
Newbie
*
Posts: 3


« Reply #1 on: February 01, 2017, 05:22:06 AM »


I have read all of the information. It is very helpful here. Is knowledge that can be put into practice.

Logged

Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2015, Simple Machines Valid XHTML 1.0! Valid CSS!
Page created in 0.065 seconds with 18 queries.