360haven works best with JavaScript enabled
[Tutorial] Yukes PAC Extractor And BPE Tutorials
Loading
Register
Page 1 of 3 123 LastLast
Results 1 to 8 of 23
  1. #1
    Developer

    brienj is offline
    Join Date : Dec 2010
    Location : Louisville, KY
    Age : 46
    Posts : 349
    Array
    Twitter: @

    Yukes PAC Extractor And BPE Tutorials

    Click image for larger version. 

Name:	WWEGamesPACExtractor.jpg 
Views:	447 
Size:	22.4 KB 
ID:	10754

    This release is a program and programming tutorial.



    Here is the README file -
    WWE GAMES / YUKES PAC Extractor v1.0 by Brien L. Johnson AKA brienj, President and Owner of XHP Creations

    This file is only allowed to be hosted at XeNTaX.com or 360Haven.com unless you give a link back. Posting this readme unedited with the download is sufficient enough. Requests to host elsewhere can be made to [email protected]


    First of all, I want to give full credit and thanks to Luigi Auriemma for his source code to decompress Yukes BPE files.


    This program opens PAC files from the Yukes wrestling games (Xbox versions), including the WWE13 PAC files which are compressed.


    Prerequisites:

    You MUST have plenty of space on your HD to extract all the files. Expect anywhere from 4 to 5 times the size of the initial PAC file size.


    Changelog:

    v1.0 - Initial Release


    To Do List:

    Use some of the code from this project to make a PAC file extractor/rebuilder.


    Instructions:

    Just start the program and open a PAC file, then choose the directory where you want the files extracted to. If the program says it completed, but only extracted 0 files, check the box to force the newer EPK8 format. The difference between the older and newer formats, is the length of the names in the header. In the older ones, the name is 4 bytes long, in the newer ones, the name is 8 bytes long. The only ones it can not auto-detect, are the newer PAC files with only one entry. There have been checks put in the auto-detector to prevent trying to extract a very large file if it is read incorrectly, and then it will re-run it as the newer style. On PAC files with only one entry though, it can't auto-detect it correctly. It shouldn't lock-up if it reads an older PAC file as a newer one, but there is the slight possibility that it could hang, and why it always tries the old format first. I've figured out some more info on how to detect the different formats, but haven't recoded the program with the detection, because this program will be replaced with a PAC file extractor/rebuilder in the near future, so this program is just to hold you over until that gets released, so you can start exploring what is contained in the PAC files.


    Extra Instructions:

    The program will overwrite all files with the same name, so if you extract the PAC file a second time, it will overwrite the files it exracted the first time. Since the program can extract THOUSANDS of files, it's ridiculous for it to ask if it can overwrite anything, so it does it by default. After the files are extracted, wait until the program tells you it is completely done processing the files before you start opening files in a hex editor or whatever. It goes through and renames files appropriately and cleans-up some left over files from the extracton process.

    This comes with additional source code with comments for a "decompressBPE" program and a "YukesBPE.dll" file to use in your own programs. For people that do not know C++ and program in .NET, I've also included a "SampleYukesBPEProgram" with source code that shows you how to use the "YukesBPE.dll" file with your .NET program. People that program in C/C++ should not need any help, although they can use the pre-compiled "YukesBPE.dll" file if they wanted, the exports are listed in the "SampleYukesBPEProgram".


    If you need any help with this program, just go to http://www.xhpcreations.com and there are links to the XHP Creations Twitter and Facebook page where I can help if needed or post your questions in the topic for the program at XeNTaX.com or 360Haven.com. If you like this work and feel like donating anything, my PayPal email is [email protected]

    Hope you enjoy!
    The Source Code from the "decompressBPE" program -
    Code:
    // not needed for ports to other systems
    #include <stdafx.h>
    #include <windows.h>
    
    // include all of the following in all target environments
    // using <cstring> instead of <string> to be compatible with newer g++
    #include <cstring>
    #include <fstream>
    #include <iostream>
    #include <stdio.h>
    
    // if this isn't included, you would have to type 'std::ifstream' instead of just 'ifstream' for example
    // lazy way to do it, but it's a small program
    using namespace std;
    
    // declare constant variables
    const char *MAGIC_HEADER = "BPE ";
    
    // function prototypes
    static int xgetc(unsigned char **in, unsigned char *inl);
    int yukes_bpe(unsigned char *in, int insz, unsigned char *out, int outsz, int fill_outsz);
    
    // only include for windows versions to use the function that most computer geeks that use the console HATE :)
    void ClearScreen();
    
    // program start function
    int main(int argc, char* argv[])
    {
    	// declare and initialize the variables used in this function
    	// will be used to make sure it has the 'magic' of a BPE file
    	char *magic = new char[4];
    	// our input buffer
    	char *inbuffer;
    	// our output buffer
    	char *outbuffer;
    	// used to calculate the compressed size
    	char *readzsize = new char[4];
    	// used to calculate the uncompressed size
    	char *readsize = new char[4];
    	// compressed size
    	int zsize;
    	// uncompressed size
    	int size;
    	// difference between size and zsize or (size - zsize)
    	int fillsize;
    
    	// make sure that there are three arguments passed to the program, which are:
    	// the program name, the input file name, and the output filename
    	if (argc != 3)
    	{
    		// comes here if there are not three arguments
    
    		// only include this function call on Windows, to make geeks mad that you cleared out the console contents :)
    		ClearScreen();
    
    		// obligatory fancy ASCII art to show what a geek you are
    		cout << "\n================================================================";
    		cout << "\n+++++++++++++====   ==   ==  ====  ==       ==++++++++++++++====";
    		cout << "\n==================  ==  ===  ====  ==  ====  ===================";
    		cout << "\n=+++++++++++++====  ==  ===  ====  ==  ====  ==++++++++++++++===";
    		cout << "\n===================    ====  ====  ==  ====  ===================";
    		cout << "\n==+++++++++++++=====  =====        ==       ====++++++++++++++==";
    		cout << "\n===================    ====  ====  ==  =========================";
    		cout << "\n===+++++++++++++==  ==  ===  ====  ==  ==========++++++++++++++=";
    		cout << "\n==================  ==  ===  ====  ==  =========================";
    		cout << "\n===     =========  ====  ==  ====  ==  ===========++++++++++++++";
    		cout << "\n==  ===  =======================================================";
    		cout << "\n=  ================================  ===========================";
    		cout << "\n=  ========  =   ====   ====   ===    ==  ===   ===  = ====   ==";
    		cout << "\n=  ========    =  ==  =  ==  =  ===  =======     ==     ==  =  =";
    		cout << "\n=  ========  =======     =====  ===  ===  ==  =  ==  =  ===  ===";
    		cout << "\n=  ========  =======  ======    ===  ===  ==  =  ==  =  ====  ==";
    		cout << "\n==  ===  ==  =======  =  ==  =  ===  ===  ==  =  ==  =  ==  =  =";
    		cout << "\n===     ===  ========   ====    ===   ==  ===   ===  =  ===   ==";
    		cout << "\n================================================================";
    
    		// gives program info and usage instructions
    		cout << "\n\nYukes BPE Decompress example program";
    		cout << "\nby Brien L. Johnson of XHP Creations";
    
    		// 'argv[0]' is the first argument, which is the name of the program
    		cout << "\n\nUsage: " << argv[0] << " <inputfile> <outputfile>";
    		cout << "\n\nWebsite: ";
    		cout << "\nhttp://www.xhpcreations.com";
    		cout << "\n\nSpecial thanks to Luigi Auriemmma for yuke_bpe.c source code!\n\n";
    
    		// return any code that says it didn't complete the task, in this case we use -1 to show an error
    		return -1;
    	}
    	else
    	{
    		// comes here if there are three arguments
    
    		// open an input filestream named 'file' in binary mode with the second argument value 'argv[1]'
    		ifstream file(argv[1], ios::in|ios::binary);
    
    		// checks if the file is open
    		if (file.is_open())
    		{
    			// make sure the starting file position is at the beginning of file
    			file.seekg(0, ios::beg);
    
    			// read the contents of the first four bytes into 'magic'
    			file.read(magic, 4);
    
    			// use a compare to make sure the first four bytes (char*) of 'magic' match our constant 'MAGIC_HEADER'			
    			if (memcmp(magic, MAGIC_HEADER, 4) != 0)
    			{
    				// if they don't match, insult the user for opening a file that isn't a BPE file
    				cout << "Open a BPE file, you numbskull!";
    
    				// return error code
    				return -1;
    			}
    			// continue code since they opened a BPE file
    
    			// set the file position to the 8th byte
    			file.seekg(8, ios::beg);
    
    			// read the contents of the next four bytes into 'readzsize'
    			file.read(readzsize, 4);
    
    			// set the file position to the 12th byte
    			file.seekg(12, ios::beg);
    
    			// read the contents of the next four bytes into 'readsize'
    			file.read(readsize, 4);
    
    			// set the value of 'zsize' using the four bytes in 'readzsize'
    			memcpy(&zsize, readzsize, sizeof(long));
    
    			// set the value of 'size' using the four bytes in 'readsize'
    			memcpy(&size, readsize, sizeof(long));
    
    			// they are only four bytes in size, but we can delete 'readzsize' and 'readsize'
    			// and free the HUGE amount of memory they are using :)
    			delete[] readzsize;
    			delete[] readsize;
    
    			// initialize input buffer 'inbuffer' to the size of 'zsize', our compressed size
    			inbuffer = new char[zsize];
    
    			// set the file position to the 16th byte
    			file.seekg(16, ios::beg);
    
    			// read the contents of the file of 'zsize' number of bytes into the input buffer 'inbuffer'
    			file.read(inbuffer, zsize);
    
    			// calculate the fillsize
    			fillsize = size - zsize;
    
    			// the all important closing of the file
    			file.close();		
    		}	
    		else
    		{
    			// if the file can't open, we of course assume they are an idiot and insult them again
    			cout << "\nUnable to open " << argv[1] << " you numbskull.  Does the file exist?\n";
    
    			// return error code
    			return -1;
    		}
    
    		// initialize output buffer 'outbuffer' to the size of 'size', our uncompressed size
    		outbuffer = new char[size];
    
    		// call the function which uncompresses the input buffer to the output buffer
    		// 'inbuffer' and 'outbuffer' are not unsigned, which the function requires, so we cast them correctly
    		// with 'reinterpret_cast<unsigned char*>'
    		int x = yukes_bpe((reinterpret_cast<unsigned char*>(inbuffer)), zsize, (reinterpret_cast<unsigned char*>(outbuffer)), size, fillsize);
    
    		// open an output filestream named 'file2' in binary mode with the third argument value 'argv[2]'
    		ofstream file2(argv[2], ios_base::out|ios_base::binary);
    
    		// checks if the file is open
    		if (file2.is_open())
    		{
    			// if the file opened, write the changed contents of the output buffer 'outbuffer' to disk
    			file2.write(outbuffer, size);
    
    			// let the person know the file saved correctly
    			cout << "\nSuccessfully saved " << argv[2] << " to disk.\n";
    
    			// return successful code
    			return 0;
    		}
    		else
    		{
    			// let the person know that the file couldn't be saved and they were probably an idiot again
    			cout << "\nCannot write " << argv[2] << " to disk, you knucklehead.  Do you have the file opened in your hex editor?\n";
    
    			// return an error code
    			return -1;
    		}
    	}
    }
    
    // the following two functions for Yukes BPE decompression were written by Luigi Auriemma
    
    static int xgetc(unsigned char **in, unsigned char *inl) {
    	int     ret;
    	if(*in >= inl) return(-1);
    	ret = **in;
    	(*in)++;
    	return(ret);
    }
    
    int yukes_bpe(unsigned char *in, int insz, unsigned char *out, int outsz, int fill_outsz) {
    	unsigned char   stack[512 + 4096];
    	int             c,
    		count,
    		i,
    		size,
    		n;
    
    	unsigned char   *inl,
    		*o,
    		*outl;
    
    	inl  = in + insz;
    	o    = out;
    	outl = out + outsz;
    
    	count = 0;
    	for(;;) {
    		i = 0;
    		do {
    			if((c = xgetc(&in, inl)) < 0) break;
    			if(c > 127) {
    				c -= 127;
    				while((c > 0) && (i < 256)) {
    					stack[i * 2] = i;
    					c--;
    					i++;
    				}
    			}
    			c++;
    			while((c > 0) && (i < 256)) {
    				if((n = xgetc(&in, inl)) < 0) break;
    				stack[i * 2] = n;
    				if(i != n) {
    					if((n = xgetc(&in, inl)) < 0) break;
    					stack[(i * 2) + 1] = n;
    				}
    				c--;
    				i++;
    			}
    		} while(i < 256);
    
    		if((n = xgetc(&in, inl)) < 0) break;
    		size = n;
    		if((n = xgetc(&in, inl)) < 0) break;
    		size |= (n << 8);
    
    		while(size || count) {
    			if(count) {
    				count--;
    				n = stack[count + 512];
    			} else {
    				if((n = xgetc(&in, inl)) < 0) break;
    				size--;
    			}
    			c = stack[n * 2];
    			if(n == c) {
    				if(o >= outl) return(-1);
    				*o++ = n;
    			} else {
    				if((count + 512 + 2) > sizeof(stack)) return(-1);
    				stack[count + 512] = stack[(n * 2) + 1];
    				stack[count + 512 + 1] = c;
    				count += 2;
    			}
    		}
    	}
    	if(fill_outsz) {    // this is what is wanted by the format
    		memset(o, 0, outl - o);
    		o = outl;
    	}
    	return(o - out);
    }
    
    // the dreaded ClearScreen function which clears all the contents out of the console window, and
    // of course it must be included in my program :)
    void ClearScreen()
    {
    	HANDLE                     hStdOut;
    	CONSOLE_SCREEN_BUFFER_INFO csbi;
    	DWORD                      count;
    	DWORD                      cellCount;
    	COORD                      homeCoords = { 0, 0 };
    
    	hStdOut = GetStdHandle( STD_OUTPUT_HANDLE );
    	if (hStdOut == INVALID_HANDLE_VALUE) return;
    
    	// get the number of cells in the current buffer
    	if (!GetConsoleScreenBufferInfo( hStdOut, &csbi )) return;
    	cellCount = csbi.dwSize.X *csbi.dwSize.Y;
    
    	// fill the entire buffer with spaces
    	if (!FillConsoleOutputCharacter(
    		hStdOut,
    		(TCHAR) ' ',
    		cellCount,
    		homeCoords,
    		&count
    		)) return;
    
    	// fill the entire buffer with the current colors and attributes
    	if (!FillConsoleOutputAttribute(
    		hStdOut,
    		csbi.wAttributes,
    		cellCount,
    		homeCoords,
    		&count
    		)) return;
    
    	// move the cursor home
    	SetConsoleCursorPosition( hStdOut, homeCoords );
    }


    The Source Code from the "SampleYukesBPEProgram" program -
    Code:
    using System;
    using System.IO;
    using System.Text;
    using System.Windows.Forms;
    // this is needed to use DLLImport
    using System.Runtime.InteropServices;
    
    namespace SampleYukesBPEProgram
    {
        public partial class Form1 : Form
        {
            // this is where we load the functions from our unmanaged dll
            [DllImport("YukesBPE.dll")]
            public static extern int yukes_bpe(byte[] input, int insz, byte[] ouput, int outsz, int fill_outsz);
            [DllImport("YukesBPE.dll")]
            public static extern int bpefile_open_save(string filename1, string filename2);
    
            // setup a constant string equal to the 'magic' of a BPE file
            public const string magicString = "BPE ";
    
            public Form1()
            {
                InitializeComponent();
            }
    
            // event handler for button1 being clicked
            private void button1_Click(object sender, EventArgs e)
            {
                // check that the open and save dialogs were not cancelled and the user selected some filenames
                if (openFileDialog1.ShowDialog() == DialogResult.OK && saveFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    // read the file into byte array 'conts'
                    byte[] conts = ReadFile(openFileDialog1.FileName);
    
                    // setup a buffer that will be used to find some values from the file
                    byte[] buff = new byte[4];
    
                    // copy first four bytes of the file to the buffer
                    Array.Copy(conts, 0, buff, 0, 4);
    
                    // checks that the four bytes are equal to the magic string "BPE "
                    if (Encoding.ASCII.GetString(buff) == magicString)
                    {
                        // copy four bytes from the 8th offset to our buffer
                        Array.Copy(conts, 8, buff, 0, 4);
    
                        // makes sure the system BitConverter is Little Endian and reverses the bytes if it isn't
                        if (!BitConverter.IsLittleEndian)
                            Array.Reverse(buff);
    
                        // get the value of the compressed size from the buffer
                        int zsize = BitConverter.ToInt32(buff, 0);
    
                        // copy four bytes from the 12th offset to our buffer
                        Array.Copy(conts, 12, buff, 0, 4);
    
                        // makes sure the system BitConverter is Little Endian and reverses the bytes if it isn't
                        if (!BitConverter.IsLittleEndian)
                            Array.Reverse(buff);
    
                        // get the value of the uncompressed size from the buffer
                        int size = BitConverter.ToInt32(buff, 0);
    
                        // reset the buffer to the uncompressed size, this buffer will be changed by the function in the dll
                        buff = new byte[size];
    
                        // compute the fillsize
                        int fillsize = size - zsize;
    
                        // create a new byte array to hold the remainder of the file, which is what we want to actually decompress
                        byte[] contents = new byte[zsize];
    
                        // copy the file contents starting at the 16th byte, where the actual BPE data is contained
                        Array.Copy(conts, 16, contents, 0, zsize);
    
                        // call the 'yukes_bpe' function in the dll which will change the contents of our buffer to the decompressed bytes
                        // and make sure the function returns the decompressed size, which means it finished successfully
                        if (yukes_bpe(contents, zsize, buff, size, fillsize) == size)
                        {
                            // you should always use a try block when dealing with file I/O
                            try
                            {
                                // write the buffer contents to the name the person chose in the saveFileDialog
                                WriteFile(buff, saveFileDialog1.FileName);
    
                                // tell them it worked
                                MessageBox.Show("Successfully saved uncompressed file " + saveFileDialog1.FileName);
                            }
                            catch
                            {
                                // it will come here if the try block failed, meaning there was a problem with the file I/O
                                MessageBox.Show("There was an error saving " + saveFileDialog1.FileName);
                            }
                        }
                        else
                        {
                            // comes here if the yukes_bpe function did not return the decompressed size
                            MessageBox.Show("There was an error decompressing " + saveFileDialog1.FileName);
                        }
                    }
                    else
                    {
                        // displays that the file does not have the correct BPE magic if it failed the check earlier
                        MessageBox.Show("Not a BPE file!");
                    }
                }
            }
    
            // event handler for button2 being clicked
            private void button2_Click(object sender, EventArgs e)
            {
                // check that the open and save dialogs were not cancelled and the user selected some filenames
                if (openFileDialog1.ShowDialog() == DialogResult.OK && saveFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    // call the 'bpefile_open_save' function in the dll and make sure it returns 0, which means it worked
                    if (bpefile_open_save(openFileDialog1.FileName, saveFileDialog1.FileName) == 0)
                    {
                        // if the function returns that it worked, tell the user it was successful
                        MessageBox.Show("Successfully saved uncompressed file " + saveFileDialog1.FileName);
                    }
                    else
                    {
                        // if the function returns anything but 0, tell the user it didn't work
                        MessageBox.Show("There was an error saving " + saveFileDialog1.FileName);
                    }
                }
            }
    
            // function to read the file contents into a byte array
            private byte[] ReadFile(string fileName)
            {
                // create a buffer
                byte[] buff = null;
    
                // create a FileStream 'fs' with the correct parameters
                FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite);
    
                // create a BinaryReader 'br' with 'fs'
                BinaryReader br = new BinaryReader(fs);
    
                // determine the length of the file, so we can set the buffer to accept it
                long numBytes = new FileInfo(fileName).Length;
    
                // set the buffer length to the file length
                buff = br.ReadBytes((int)numBytes);
    
                // close the BinaryReader and FileStream
                br.Close();
                fs.Close();
    
                // return the buffer contents
                return buff;
            }
    
            // function to write a byte array to a file
            private void WriteFile(byte[] buff, string fileName)
            {
                // this is a check to make sure the file is not a read-only file, and if it is, remove the read-only property
                System.IO.FileInfo fi = new System.IO.FileInfo(fileName);
                if (fi.IsReadOnly && File.Exists(fileName))
                {
                    fi.IsReadOnly = false;
                }
    
                // create a FileStream 'fs' with the correct parameters
                FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite);
    
                // create a BinaryWriter 'bw' with 'fs'
                BinaryWriter bw = new BinaryWriter(fs);
    
                // write the buffer contents
                bw.Write(buff);
    
                // close the BinaryWriter and FileStream
                bw.Close();
                fs.Close();
            }
        }
    }


    Enjoy!

    You can download the programs, dll file, and full source code for everything but the extractor here -

    http://www.360haven.com/forums/downl...o=file&id=1023

  2. The Following 21 Users Say Thank You to brienj For This Useful Post:

    + Show/Hide list of the thanked


  3. #2
    Developer

    Arjun The Man is offline
    Join Date : Aug 2012
    Location : In ASIA
    Posts : 821
    Array
    Thanks a million times brienj you just saved my old boring + 8 x800 hexing Lol

    I blame Tapatalk for any mistake in this post :)
    Downloads : 23 || Uploads : 3 || Rep Power : 2831 || Posts : 821 || Thanks : 236 || Thanked 375 Times in 116 Posts



  4. #3
    The Immortal God
    Rpg_Fan

    CloudStrife7x is offline
    Join Date : Dec 2010
    Location : Unknown
    Age : 29
    Posts : 18,760
    Array
    Twitter: @

    Re: Yukes PAC Extractor And BPE Tutorials

    great tutorial shared brienj :)
    Downloads : 157 || Uploads : 0 || Rep Power : 22145 || Posts : 18,760 || Thanks : 4,451 || Thanked 3,095 Times in 2,607 Posts



  5. #4
    Retired Staff

    thegutta is offline
    Join Date : Jun 2011
    Location : On Top Of The World
    Posts : 10,475
    Array
    Twitter: @
    Nice tut brienj great share bro :)
    Downloads : 47 || Uploads : 0 || Rep Power : 13175 || Posts : 10,475 || Thanks : 3,231 || Thanked 1,396 Times in 1,224 Posts




  6. #5
    Eternal Dragoon
    Rpg_Fan

    Serious_M is offline
    Join Date : Dec 2010
    Location : Netherlands , Amsterdam
    Age : 33
    Posts : 13,032
    Array

    Re: Yukes PAC Extractor And BPE Tutorials

    very nice tut you made brienj
    Downloads : 57 || Uploads : 1 || Rep Power : 16104 || Posts : 13,032 || Thanks : 3,661 || Thanked 1,791 Times in 1,446 Posts


    Serious_M

  7. #6
    Developer

    brienj is offline
    Join Date : Dec 2010
    Location : Louisville, KY
    Age : 46
    Posts : 349
    Array
    Twitter: @

    Re: Yukes PAC Extractor And BPE Tutorials

    The evolution to the next step -


    Link to news story on Facebook page

  8. #7
    Developer

    Arjun The Man is offline
    Join Date : Aug 2012
    Location : In ASIA
    Posts : 821
    Array
    Quote Originally Posted by brienj View Post
    The evolution to the next step -


    Link to news story on Facebook page
    If this will have a re builder and a offset fixer then this is the best tool ever made, thanks for letting us dream, and I hope this dream comes true soon. :)



    I blame Tapatalk for any mistake in this post :)
    Downloads : 23 || Uploads : 3 || Rep Power : 2831 || Posts : 821 || Thanks : 236 || Thanked 375 Times in 116 Posts



  9. #8
    Barry Stone

    Re: Yukes PAC Extractor And BPE Tutorials

    Every time I try to extract any pac file it just gives me Error Parsing!

 

 
Page 1 of 3 123 LastLast

Similar Threads

  1. [Release] Yukes PAC Archiver v1.3.2.0
    By brienj in forum Xbox 360 Modding Programs
    Replies: 205
    Last Post: 04-05-2016, 12:52 AM
  2. Need help with Yukes WWE game music
    By kmvegas in forum Xbox 360 Modding Discussion
    Replies: 4
    Last Post: 01-29-2013, 11:21 PM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
This website uses cookies
We use cookies to store session information to facilitate remembering your login information, to allow you to save website preferences, to personalise content and ads, to provide social media features and to analyse our traffic. We also share information about your use of our site with our social media, advertising and analytics partners.
     

About 360haven

    360haven is an Forum Devoted To Game modding Fans from all over the world.

    An Awesome Community of Xbox 360 Gamers, Modders and Developers who Create & Share Tutorials, Applications, Gfx, Trainers and Gamesaves.

    A haven for the l33t.
    A scarce paradise for modders.

Like this page

Google+