Jump to content

Full Auto (Xbox 360) - *.RXX / *.PIX / *.PIT / *.XZP


Go to solution Solved by DKDave,

Recommended Posts

  • 10 months later...
Posted
On 6/22/2024 at 4:29 PM, UndercoverBoy833 said:

to me, .rxx was music file according to the name of the song in it. but I also have no idea either

Do PIXs contain 3D models and are there tools that can extract them?

Posted
On 5/10/2025 at 2:15 AM, mrmaller1905 said:

Do PIXs contain 3D models and are there tools that can extract them?

dunno myself, like you I'm trying to grab the models and textures too. And the maps if that's possible, because I want to try to connect them all together so I can see what it'd look like as one big free roam city map

  • Engineers
Posted
On 5/10/2025 at 11:15 AM, mrmaller1905 said:

Do PIXs contain 3D models and are there tools that can extract them?

Looks compressed or encrypted (or both). You could try a comtype scan (see description of quickbms).

  • Engineers
Posted (edited)

Thanks! Using offzip with fa_t111.pix results in some .vap (textures?) and .dat files.

Found some strings:

Quote

rtdXenon/fa_PRP_Sign_BillboardSideOfBuildingChunk
fa_prp_sign_e_billboard_perpendicularbaseChunk28

fa_Sweatshop_garageChunk90

fa_Tanker_truckdmg_stacks

One .dat checked:

mesh_viewer_pix-dat.png

Face indices are a little bit annoying. This sub mesh built at least from 178 vertices:

mesh_viewer_178vertices.png

Edited by shak-otay
  • Like 1
Posted (edited)
1 hour ago, shak-otay said:

Thanks! Using offzip with fa_t111.pix results in some .vap (textures?) and .dat files.

Found some strings:

One .dat checked:

mesh_viewer_pix-dat.png

Face indices are a little bit annoying. This sub mesh built at least from 178 vertices:

mesh_viewer_178vertices.png

OH SHIT that's the destructible parts of one of the maps! great find! (T111 is the map Turnpike according to the files!)

The vehicles have to be in one of those .pix then....

Edited by FullAuto_Enjoyer
  • Engineers
Posted (edited)
15 hours ago, FullAuto_Enjoyer said:

The vehicles have to be in one of those .pix then....

But in which one? I've collected 135 small point clouds from a .dat from fa_frontend.pix but can't make much sense of it:

blender-app_135sub_meshes.png

Other sub meshes with suiting face indices are not very impressive (Tfa_PRP_constructionBarrierChunk3, Debris) :

mesh_viewer_barrier.png

fa_PRP_group_SmallPylon_A:

mesh_viewer_3-pylons.png

Edited by shak-otay
mesh correction
Posted

The models are in the .drp files, once extracted from the .pix archives.  Textures are .x2m (not sure what format)

Most models have several submeshes, so it will need proper analysis and a script to get all of the mesh data properly.  Just a manual example of one submesh:

image.thumb.png.0070c2c6c149133455492d58e7988dcb.png

  • Like 2
  • Engineers
Posted

I don't get it. Pointers are in LittleEndian but vertices + index is BigEndian.

Also textures are 2 byte swap. Classic x360.

  • Engineers
Posted (edited)

Just wait on miracle to happen.

Anyway here is struct of x2m. Already wrote Noesis script, but don't know how to read external file "textures.pit" where are stored textures with better resolution.

//------------------------------------------------
//--- 010 Editor v14.0 Binary Template
//
//      File: 
//   Authors: 
//   Version: 
//   Purpose: 
//  Category: 
// File Mask: 
//  ID Bytes: 
//   History: 
//------------------------------------------------
LittleEndian();
struct
{
    uint32 RawDataSize;
    char Sign[9];
    string File;
    uint16 TextureWidth_Low;
    uint16 TextureHeight_Low;
    uint16 TextureWidth_High;
    uint16 TextureHeight_High;
    ubyte Unknown_0,Unknown_1,Unknown_2,Unknown_3;
    uint32 Unknown_4;
    ubyte PixelFormat,Unknown_6,Unknown_7,Unknown_8;
    uint32 TextureData_Low;
    uint32 TextureData_High;
    uint32 TextureDataOffset_High;
    byte RawData[TextureData_Low];
}Texture;

And here's generic BMS script for decompressed files from pix. Maybe it's not compatible with all files...

###################################
get BaseFileName basename

get Files uint32

for i = 0 < Files
	savepos InfoOffset
	get RawDataSize uint32
	getdstring Dummy 0x09
	get FileName string
	savepos RawOffset
	
	xmath InfoSize "RawOffset - InfoOffset"
	getdstring RawData RawDataSize
	
	string InfoFileName p= "%s/%s" BaseFileName FileName
	string RawFileName p= "%s/%s" BaseFileName FileName
	
	append 0
	log InfoFileName InfoOffset InfoSize
	log RawFileName RawOffset RawDataSize
next i

 

Edited by h3x3r
Posted
20 minutes ago, h3x3r said:

Just wait on miracle to happen.

Anyway here is struct of x2m. Already wrote Noesis script, but don't know how to read external file "textures.pit" where are stored textures with better resolution.

//------------------------------------------------
//--- 010 Editor v14.0 Binary Template
//
//      File: 
//   Authors: 
//   Version: 
//   Purpose: 
//  Category: 
// File Mask: 
//  ID Bytes: 
//   History: 
//------------------------------------------------
LittleEndian();
struct
{
    uint32 RawDataSize;
    char Sign[9];
    string File;
    uint16 TextureWidth_Low;
    uint16 TextureHeight_Low;
    uint16 TextureWidth_High;
    uint16 TextureHeight_High;
    ubyte Unknown_0,Unknown_1,Unknown_2,Unknown_3;
    uint32 Unknown_4;
    ubyte PixelFormat,Unknown_6,Unknown_7,Unknown_8;
    uint32 TextureData_Low;
    uint32 TextureData_High;
    uint32 TextureDataOffset_High;
    byte RawData[TextureData_Low];
}Texture;

And here's generic BMS script for decompressed files from pix. Maybe it's not compatible with all files...

###################################
get BaseFileName basename

get Files uint32

for i = 0 < Files
	savepos InfoOffset
	get RawDataSize uint32
	getdstring Dummy 0x09
	get FileName string
	savepos RawOffset
	
	xmath InfoSize "RawOffset - InfoOffset"
	getdstring RawData RawDataSize
	
	string InfoFileName p= "%s/%s" BaseFileName FileName
	string RawFileName p= "%s/%s" BaseFileName FileName
	
	append 0
	log InfoFileName InfoOffset InfoSize
	log RawFileName RawOffset RawDataSize
next i

 

Can you also write a file format specification for Full Auto PIX files that are compressed with zlib?

  • Engineers
Posted (edited)

For the meshes it's just to find start of face indices for the next sub mesh, since there's more vertices than 1280.

(Offsets are different from DKDave's because I used offzip for unpacking.)

Hex2obj0.25b-W7med_tanker_truck.png

This sub mesh uses shorts for uvs:

)cab.png.68aff7eadb4d4b899eebfb09eb579c89.png

 

There's floats interspersed (position offset maybe) before the face indices continue, after blue arrow:

mspaint_float_before_FIs.png.4fdc88fb0c084c9821cc0de21f282800.png

 

So the next submesh has 45 face indices (24 vertices) only:

mesh_viewer_tank_truck_2nd_sub_mesh.png

3rd sub mesh:

mesh_viewer_jEHnukP7Rd.png

4th sub mesh:

mesh_viewer_exhaust.png

(headlights' glasses skipped, 137 vertices)

last one, maybe. 1967 vertices :

mesh_viewer_D6Yj4beOSk.png

Edited by shak-otay
update
  • Engineers
Posted
3 hours ago, mrmaller1905 said:

Can you also write a file format specification for Full Auto PIX files that are compressed with zlib?

I don't think so... There is no TOC.

  • Solution
Posted

Here's a QuickBMS script to extract the .pix archives with proper names.  You can analyse it and write a file spec from it.

 

 

pix.zip

  • Like 2
  • Thanks 1
  • Engineers
Posted

Thanks to DKDave for initial script. Here's updated. Now it unpacks textures with better resolution.

 

# Full Auto (XBox 360, 2006)
# .PIX archive extract
# QuickBMS script by DKDave, 2025

open FDSE "textures.pit" 1

Get TEMPNAME basename
Get FILE_END asize
Math OFFSET = 0

For A = 0
	Goto OFFSET
	Get ZSIZE Long
	Get SIZE Long

	If ZSIZE = 0
		Break
	Endif

	Padding 0x800
	SavePos OFFSET

	CLog MEMORY_FILE OFFSET ZSIZE SIZE

	Goto 0 -1
	Get FILES Long -1

# Process uncompressed data in memory file

	For B = 0 < FILES
		Get SIZE Long -1
		SavePos STROFF -1
		Get FILENAME String -1
		SavePos OFFSET2 -1
		Goto STROFF -1
		Strlen STRLEN FILENAME -1
		math STRLEN - 3
		GetDString DUMMY STRLEN -1
		Get EXT String -1
		
		if EXT = "x2m"
			print "%EXT%"
			GetDString DUMMY 0x18 -1
			Get TEXTURE_DATA_HIGH Long -1
			Get TEXTURE_OFFSET_DATA_HIGH Long -1
			Goto OFFSET2 -1
			if TEXTURE_DATA_HIGH != 0
				Log FILENAME TEXTURE_OFFSET_DATA_HIGH TEXTURE_DATA_HIGH 1
				append -1
				Log FILENAME OFFSET2 32 -1
			else
				Log FILENAME OFFSET2 SIZE -1
			endif
		else
			Log FILENAME OFFSET2 SIZE -1
		endif
		Goto SIZE -1 SEEK_CUR
	Next B

	Math OFFSET + ZSIZE

Next A

And here's Noesis script for them... There may be another pixel format I don't have covered...

from inc_noesis import *
import noesis
import rapi
import os

def registerNoesisTypes():
   handle = noesis.register("Fullauto", ".x2m")
   noesis.setHandlerTypeCheck(handle, noepyCheckType)
   noesis.setHandlerLoadRGBA(handle, noepyLoadRGBA)
   noesis.logPopup()
   return 1
        
def noepyCheckType(data):
   bs = NoeBitStream(data)
   if len(data) < 20:
      return 0
   return 1
   
def noepyLoadRGBA(data, texList):
    bs = NoeBitStream(data)
    BaseName = rapi.getExtensionlessName(rapi.getLocalFileName(rapi.getInputName()))
    cPos = bs.tell()
    bs.read(4)
    Check = bs.readUInt()
    bs.seek(cPos, NOESEEK_ABS)
    
    if Check == 0:
        TextureWidth = bs.readUShort()
        TextureHeight = bs.readUShort()
        bs.read(4)
    else:
        bs.read(4)
        TextureWidth = bs.readUShort()
        TextureHeight = bs.readUShort()

    Unknown_0 = bs.readUByte()
    Unknown_1 = bs.readUByte()
    Unknown_2 = bs.readUByte()
    Unknown_3 = bs.readUByte()
    Unknown_4 = bs.readUInt()
    PixelFormat = bs.readUByte()
    Unknown_6 = bs.readUByte()
    Unknown_7 = bs.readUByte()
    Unknown_8 = bs.readUByte()
    TextureData_Low = bs.readUInt()
    TextureData_High = bs.readUInt()
    TextureDataOffset_High = bs.readUInt()
    
    if Check != 0:
        data = bs.readBytes(TextureData_High)
    else:
        data = bs.readBytes(TextureData_Low)

    if PixelFormat == 82:
        data = rapi.imageUntile360DXT(rapi.swapEndianArray(data, 2), TextureWidth, TextureHeight, 8)
        texFmt = noesis.NOESISTEX_DXT1
        print("Pixel Format > DXT1 >", PixelFormat)
    elif PixelFormat == 84:
        data = rapi.imageUntile360DXT(rapi.swapEndianArray(data, 2), TextureWidth, TextureHeight, 16)
        texFmt = noesis.NOESISTEX_DXT5
        print("Pixel Format > DXT5 >", PixelFormat)
    elif PixelFormat == 113:
        data = rapi.imageUntile360DXT(data, TextureWidth, TextureHeight, 16)
        data = rapi.imageDecodeDXT(rapi.swapEndianArray(data, 2), TextureWidth, TextureHeight, noesis.FOURCC_ATI2)
        texFmt = noesis.NOESISTEX_RGBA32
        print("Pixel Format > ATI2 >", PixelFormat)
    else:
        print("Unknown Pixel Format > ", PixelFormat)
            
    texList.append(NoeTexture(rapi.getInputName(), TextureWidth, TextureHeight, data, texFmt))
    return 1

 

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...