Jump to content

Recommended Posts

  • Members
Posted (edited)
23 hours ago, Taruncreation said:

Apparently, the only possible way I see to get some decent working asset from Asphalt Legends Unite would be using Ninja Ripper.

I got my hands on the latest version and gave it a go...it's bit messy indeed but yeah it works!

image.png.83679be0d3f8bb9762b86f27280d4188.png

 

are the rippings in a 1:1 scale, dimensions and no skewed model after using Ninja Ripper and import the scene into blender? Btw thx for the response. In fact I wanna collect more of Asphalt Legends Unite all unicorn cars as of today and from recent updates of the games

Edited by UndercoverBoy833
Posted (edited)
4 hours ago, UndercoverBoy833 said:

are the rippings in a 1:1 scale, dimensions and no skewed model after using Ninja Ripper and import the scene into blender? Btw thx for the response. In fact I wanna collect more of Asphalt Legends Unite all unicorn cars as of today and from recent updates of the games

Yeah, as I said it's messy...since I am ripping from the Garage scene...it comes with wheels turned right and also the whole geometry sort of rotated by a few angles on all axis...I have attached the original model and the one I tried to edit a bit...might wanna check different channels for correct UV...textures and UV are fine tho.

Arash Imperium

image.png.14aedbca69662849c15c612c87596775.png

Edited by Taruncreation
  • Engineers
Posted (edited)

Here's 010 editor template for jtex files. I will write bms for decompress + noesis for preview later...

LittleEndian();OutputPaneClear();

local uint32 i,j,k,l,m,n,TotalFileSize=FileSize();
local string FileName=GetFileName(),FilePath=FileNameGetPath(FileName,true),BaseName=FileNameGetBase(FileName,false);

struct
{
    ubyte Version;
    char JTEXSign[4];
    uint32 Unknown_0;
    uint32 Unknown_1;
}Header;

struct
{    
    uint32 TextureTableSize;
    uint32 TextureInfoSize;
    uint32 Unknown_0;
    uint16 Unknown_1;
    
    struct
    {
        uint16 TextureWidth;
        uint16 TextureHeight;
        ubyte Unknown_0;
        ubyte PixelFormat;
        ubyte Unknown_1;
        ubyte Unknown_2;
        uint16 Unknown_3;
        ubyte Unknown_4;
        ubyte MipMap;
        uint32 Unknown_5;
        float Unknown_6;
        float Unknown_7;
        uint16 TextureWidth_t;
        uint16 TextureHeight_t;
        
        struct
        {
            uint32 MipMapTableSize;
            uint32 MipMapInfoSize;
            uint32 Unknown_0;
            uint16 Unknown_1;
            
            struct
            {
                uint32 MipMapBlockSize;
                uint32 CompressedSize; // - 8
                uint32 DecompressedSize;
                ubyte CompFlag;
                ubyte Unknown_1;
                uint32 Unknown_2;
                float Unknown_3;
                if (CompFlag == 0)
                    byte Buffer[DecompressedSize];
                else
                    byte ZSDTBuffer[CompressedSize - 8];
            }MipMapInfo[MipMap]<optimize=false>;
        }MipMapTable;
    }TextureInfo;
}TextureTable;
Edited by h3x3r
  • Like 2
  • Engineers
Posted (edited)

I checked jmox files but mesh needs transformation...

image.png.1454bc5b74c13e6f029464ee5f25919a.png

Here's quick sum up content of *.pack archives.

main =    ? > mixed
 mdc = jmox > models cars
 mde = jmox > models environment
  so =  xvs > sounds
  lm = jtex > textures
 prb = jtex > textures
 gin = jtex > textures

Edited by h3x3r
  • Like 2
  • Engineers
Posted

Well so here's everything I know so far.

Models are pain. Can't figure out monstrous table which has info about buffer id, vertex count, index count. I output only element buffers. I only know about vertex buffer. At cars they are mostly 8 bytes stride, int16 data type.

Not sure what are others buffers. But they have type id.

 

Textures on the other hand are simple. You can get pretty much all of them.

I also looked into the sound files. Some are wav, but most of them are unexplored... need some time to research. Also those wav files are named by id which is described in track_table file which is also unexplored yet...

 

So here's bms script. You can use it on any file from *.pack file which you can unpack with 7Zip.

Spoiler
##############################
#### Asphalt 9 Legends PC ####
##############################

get BaseFileName basename

get Version ubyte
getdstring Sign 0x3

if Sign == jte
	CallFunction jtex_unpack
elif Sign == jmo
	CallFunction jmox_unpack
elif Sign == xvs
	CallFunction xvs_unpack
elif Sign == oxa
	CallFunction voxarch_unpack
elif Sign == jcl
	CallFunction jclx_unpack
elif Sign == jan
	CallFunction janx_unpack
endif


StartFunction jtex_unpack
	comtype zstd
	goto 0
	
	# Header
	get Version ubyte
	getdstring JTEXSign 0x4
	get Unknown_0 uint32
	get Unknown_1 uint32
	
	# Texture Table
	get TextureTableSize uint32
	get TextureInfoSize uint32
	get Unknown_0 uint32
	get Unknown_1 ushort
	
	# Texture Info
	get TextureWidth ushort
	get TextureHeight ushort
	get Unknown_0 ubyte
	get PixelFormat ubyte
	get Unknown_1 ubyte
	get Unknown_2 ubyte
	get Unknown_3 ushort
	get Unknown_4 ubyte
	get MipMap ubyte
	get Unknown_5 uint32
	get Unknown_6 float
	get Unknown_7 float
	get TextureWidth_t ushort
	get TextureHeight_t ushort
	
	# MipMap Table
	get MipMapTableSize uint32
	get MipMapInfoSize uint32
	get Unknown_0 uint32
	get Unknown_1 ushort
	
	# MipMap Info
	get MipMapBlockSize uint32
	get CompressedSize uint32
	math CompressedSize - 8
	get DecompressedSize uint32
	get CompFlag ubyte
	get Unknown_1 ubyte
	get Unknown_2 uint32
	get Unknown_3 float
	savepos Offset
	string Name p "_Unpacked/textures/%s.jtex" BaseFileName
	
	if CompFlag == 0
		append 0
		log Name 27 6
		log Name 77 4
		log Name Offset DecompressedSize
	else
		append 0
		log Name 27 6
		log Name 77 4
		clog Name Offset CompressedSize DecompressedSize
	endif
EndFunction


StartFunction jmox_unpack
	comtype zstd
	goto 0
	
	# Header
	get Version ubyte
	getdstring JMOXSign 0x6
	get Unknown_0 uint32
	get Unknown_1 uint32
	
	# Resource Info
	get Unknown_0 ushort
	get Unknown_1_Offset uint32
	get Unknown_1_Count ushort
	get Unknown_2_Offset uint32
	get Unknown_2_Count ushort
	get ChunkInfoOffset uint32
	get ChunkCount ushort
	get Unknown_3_Offset uint32
	get Unknown_3_Count uint32
	get Unknown_4 uint32
	get Unknown_5 uint32
	
	goto ChunkInfoOffset
	
	for i = 0 < ChunkCount
		get ElementType ubyte
		get Unknown_1 ubyte
		get CompressedSize uint32
		get DecompressedSize uint32
		savepos Offset
		
		if CompressedSize != 0
			getdstring Data CompressedSize
		endif
		
		string Name p "_Unpacked/%s/models/buffer_id_%u_element_type_%u.dat" BaseFileName i ElementType
		if CompressedSize != 0
			clog Name Offset CompressedSize DecompressedSize
		endif
	next i
EndFunction


StartFunction xvs_unpack
	goto 0
	
	# Header
	get Version ubyte
	getdstring XVSSign 0x3
	get InfoOffset uint32
	getdstring Unknown 0x8
	
	# Resource Table Info
	get DataOffset uint32
	get TotalFileSize uint32
	getdstring Sign 0x4
	get ResourceTableSize uint32
	
	# Resource Info
	get ResourceCount uint32
	
	for i = 0 < ResourceCount
		get TrackId uint32
		get Channels uint32
		get Frequency uint32
		get ResourceOffset uint32
		get ResourceSize uint32
		get UncompressedSize uint32
		get Unknown_0 uint32
		get Unknown_1 float
		get Unknown_2 uint32
		math ResourceOffset + DataOffset

		string Name p "_Unpacked/%s/sounds/track_%u.wav" BaseFileName TrackId
		log Name ResourceOffset ResourceSize
	next i
	savepos TrackTableOffset
	xmath TrackTableSize "DataOffset - TrackTableOffset"
	string Name p "_Unpacked/%s/sounds/track_table.dat" BaseFileName
	log Name TrackTableOffset TrackTableSize
	
EndFunction


StartFunction voxarch_unpack
	goto 0
	
	# Header
	getdstring VOXARCHSign 0x8
	get Unknown_0 uint32
	get Unknown_1 uint32

	# Resource Table Info
	get ResourceCount uint32
	get NameSectionSize uint32
	get ResourceTableOffset uint32
	get Unknown_0_Offset uint32
	get NameSectionTableOffset uint32
	get Unknown_1_Offset uint32
	get NameSectionOffset uint32
	get Unknown_2 uint32
	get Unknown_3 uint32
	get Unknown_4_Offset uint32
	get Unknown_5_Offset uint32
	get SoundDefinitionOffset uint32

	goto ResourceTableOffset
	
	# Resource Info
	for i = 0 < ResourceCount
		get Unknown_0 uint32
		get Unknown_1 uint32
		get ResourceSize[i] uint32
		get ResourceOffset[i] uint32
	next i
	
	goto NameSectionTableOffset
	
	# Resource Name Info
	for i = 0 < ResourceCount    
		get ResourceNameOffset uint32
		math ResourceNameOffset + NameSectionOffset
		savepos cPos
		goto ResourceNameOffset
		get FileName[i] string
		goto cPos
	next i
	
	goto SoundDefinitionOffset
	get DefinitionName string
	
	for i = 0 < ResourceCount
		string Name p "_Unpacked/%s/sounds/%s/%s" BaseFileName DefinitionName FileName[i]
		log Name ResourceOffset[i] ResourceSize[i]
	next i
EndFunction


StartFunction jclx_unpack
	comtype zstd
	goto 0
	
	# Header
	get Version ubyte
	getdstring JCLXSign 0x6
	get Unknown_0 uint32
	get Unknown_1 uint32
	
	# Resource Info
	get Unknown_0 uint32
	get Unknown_1 ubyte
	get Unknown_2 uint32
	get Unknown_3 uint32
	get CompressedSize uint32
	get DecompressedSize uint32
	savepos Offset
	
	string Name p "_Unpacked/%s.jclx" BaseFileName
	clog Name Offset CompressedSize DecompressedSize
EndFunction


StartFunction janx_unpack
	comtype zstd
	goto 0
	
	# Header
	get Version ubyte
	getdstring JANXSign 0x6
	get Unknown_0 uint32
	get Unknown_1 ushort
	get Unknown_2 ushort
	
	# Resource Info
	get ResourceCount ubyte
	
	for i = 0 < ResourceCount
		get Unknown_0 uint32
		get CompressedSize uint32
		get DecompressedSize uint32
		savepos Offset
		getdstring ZSTDBuffer CompressedSize
		string Name p "_Unpacked/%s/%u.janx" BaseFileName i
		clog Name Offset CompressedSize DecompressedSize
	next i
EndFunction

 

And here's Noesis for *.jtex files.

from inc_noesis import *
import noesis
import rapi
import os

def registerNoesisTypes():
   handle = noesis.register("Asphalt 9 Legends - Texture", ".jtex")
   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()))
    TextureWidth = bs.readUShort()
    TextureHeight = bs.readUShort()
    bs.read(1)
    PixelFormat = bs.readUByte()
    BufferSize = bs.readUInt()
    data = bs.readBytes(BufferSize)
    
    if PixelFormat == 34:
        print("Pixel Format > BC7 ", PixelFormat)
    elif PixelFormat == 35:
        print("Pixel Format > BC6H ", PixelFormat)
    elif PixelFormat == 36:
        print("Pixel Format > BC5 ", PixelFormat)
    elif PixelFormat == 5:
        print("Pixel Format > RGB8", PixelFormat)
    elif PixelFormat == 6:
        print("Pixel Format > RGBA8", PixelFormat)
    else:
        print("Unknown Pixel Format > ", PixelFormat)
    

    if PixelFormat == 34:
        data = rapi.imageDecodeDXT(data, TextureWidth, TextureHeight, noesis.FOURCC_BC7)
        texFmt = noesis.NOESISTEX_RGBA32                        
    elif PixelFormat == 35:
        data = rapi.imageDecodeDXT(data, TextureWidth, TextureHeight, noesis.FOURCC_BC6H)
        texFmt = noesis.NOESISTEX_RGBA32
    elif PixelFormat == 36:
        data = rapi.imageDecodeDXT(data, TextureWidth, TextureHeight, noesis.FOURCC_BC5)
        texFmt = noesis.NOESISTEX_RGBA32
    elif PixelFormat == 5:
        texFmt = noesis.NOESISTEX_RGB24
    elif PixelFormat == 6:
        texFmt = noesis.NOESISTEX_RGBA32           
    texList.append(NoeTexture(rapi.getInputName(), TextureWidth, TextureHeight, data, texFmt))
    return 1

 

  • Like 2
Posted

I also looked at these a while ago.  It uses the same jmox format as Speedstorm, so decompressing the data blocks is the easy part.  However, the actual info table at the end of the file is weird.  As mentioned above, it contains lots of unknown data, but it does have the submesh info.  Not sure if there's a model script for Speedstorm, but it might be compatible if you can find one.

 

 

  • Engineers
Posted (edited)

Well i searched for pattern and found exact count of Table_3. But size of each info varies.

image.thumb.png.71a7b898f8cf2ea7257261c74cd2c1f7.png

Anyway there's a script by Durik, but not for free.

Edited by h3x3r
Posted
On 8/2/2025 at 5:27 PM, Taruncreation said:

Yeah, as I said it's messy...since I am ripping from the Garage scene...it comes with wheels turned right and also the whole geometry sort of rotated by a few angles on all axis...I have attached the original model and the one I tried to edit a bit...might wanna check different channels for correct UV...textures and UV are fine tho.

Arash Imperium

image.png.14aedbca69662849c15c612c87596775.png

Would you mind sending the model for the formula e gen 3 evo? 🙏

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...