Open lf94 opened 3 years ago
From some quick research here on GitHub it seems there are two other projects which attempt to write a VPK extractor:
Inspecting the vpk with hexdump
leads me to believe it's a variant...
After some more searching, it appears https://dev.cra0kalo.com/ has worked on a closed source VPK extractor over the years. That really sucks. Looks like I'm going to have to write one based on the available knowledge.
https://wiki.modme.co/wiki/apps/Legion.html seems to be the leader in this space... Again, closed source. :/
englishclient_mp_rr_canyonlands_64k_x_64k.bsp.pak000_dir.vpk seems to be a proper vpk file with file listings inside. I suppose this maps to its sibling vpk file which actually contains the contents...
Currently modifying https://github.com/ValvePython/vpk to fit the slightly modified format.
Edit: Aaaand that tool is a mess too. I'm just going to write something simple in Rust. I only care that it supports Apex.
Edit2: Spent a good amount of time looking at the vpk file but still don't feel confident about understanding it enough to do a full walk of the archive. I may see what Apex does in x64dbg tomorrow.
the pak000_dir.vpk
s host all headers which point to files, cra0kalo has said they were going to release their source code for opening .vpks but they haven't yet
IIRC you can still get cra0's tool just to extract the files, I've extracted most of Apex's files into a folder on my pc and I just load them with bsp_tool when I want to check something
cra0 explained the .vpk header here: https://forum.xentax.com/viewtopic.php?f=10&t=11208 but I think it's changed since 2014
@snake-biscuits I also had the thought it's very possible the collision mesh is stored in rpak files, since it appears they use rpaks for more modular updates, and I can imagine from a development point of view that collision needs to be updated way more often than graphical mesh.
So maybe I should focus my effort on learning rpak format and defer the current vpk endeavor to cra0kalo... From what I can tell the authors of Legion figured out rpak format, so I'll check out what they're doing.
Edit: Look like Legion is "packed". Very high entropy and the disassembly is mostly not good. I read the EULA.txt too, what a nightmare, specifically the Privacy section. Why is this community so keen on being secretive?... Makes me afraid this tool is doing other things than just asset extraction...
"LEGION" END USER LICENSE AGREEMENT
IT IS YOUR RESPONSIBILITY TO READ THIS AGREEMENT CAREFULLY.
This EULA governs your use of the Legion software. This EULA may be updated, revised, or otherwise modified at any time, and new versions will be included with automatic updates of Legion. Your use of the Legion software constitutes your acceptance of these terms.
You acknowledge and agree that this software is licensed, not sold, to you and at all times remains property of DTZxPorter. By installing, copying, or using this software, you agree to the terms of this agreement.
--------------------
1. License
DTZxPorter hereby grants you the non-exclusive, non-transferable, limited license to use this software for your personal, non-commercial use in creating user-created content for Apex, and to distribute the direct download link provided by DTZxPorter.
1A. Credit
You must provide credit to Legion / (DTZxPorter) for work derived from the use of Legion.
2. Ownership
DTZxPorter retains all rights to the software. Any persons found to be copying, reproducing or distributing all or any portion of the software will be permanently banned from using all previous and future software provided by DTZxPorter / Avia Creations.
3. Conditions
By installing or otherwise using this software, you agree NOT to:
a. Commercially exploit the software;
b. Distribute, license, sell, lease, rent or otherwise transfer or assign the software, without the explicit written consent of DTZxPorter, except for archival purposes;
c. Directly or indirectly, in any form, copy, reproduce, prepare derivative works of, modify, decompile, reverse engineer, decompile, disassemble or otherwise attempt to derive source code from the software;
d. Remove any proprietary notices incorporated in or with the software;
e. Rehost or redistribute this software anywhere that is not on the Avia Creations website;
4. Protection
This software may include measures to control access to the software, control access to certain features or content, or prevent unauthorized copies of the software. You may not interfere with these measures or otherwise attempt to disable or circumvent these features.
5. Privacy
This software may collect data such as the IP address of a user, hardware information, and other such data. This data is used internally by Avia Creations (Modme) for analysis and review, and when stored is obfuscated so the user's privacy is maintained. All information is intended to be anonymous information that does not disclose your identity or otherwise personal information. Avia Creations will exercise reasonable effort to avoid disclosure of any such information to third parties. Avia Creations does not guarantee that such information will not be disclosed to third parties.
6. Warranty & Liability
This software is provided "as-is" and without warranty of any kind. IN NO EVENT WILL DTZXPORTER BE LIABLE FOR ANY DAMAGES RESULTING FROM POSSESSION OR MALFUNCTION OF THE SOFTWARE OR UPDATES TO THE SOFTWARE, INCLUDING BUT NOT LIMITED TO, DAMAGES TO PROPERTY, COMPUTER FAILURE OR MALFUNCTION, LOSS OF GOODWILL.
7. Termination
Failure to adhere to the terms in this agreement while using the software will terminate this agreement. The agreement can also be terminated by you, or by DTZxPorter. Upon any termination, you must destroy any copies of the software, and updates to the software, in your possession. Failure to adhere to this agreement will also result in the user being permanently banned from using all previous and future software provided by DTZxPorter / Avia Creations, including the website.
--------------------
Legion | Copyright 2021 DTZxPorter. All rights reserved.
So already I have voided the licence and now I should be banned from Modme and further software downloads :slightly_smiling_face:
Using https://zenhax.com/viewtopic.php?t=3461 I should be able to reverse the rpak format. The dll is not mangled like every other single thing I've looked at so far :slightly_smiling_face: The decompression routine is not very large either.
You might find some of the tools & modding guides here helpful: https://noskill.gitbook.io/titanfall2/
Someone recently sent me this, it's the apex firing range with an edited vertex lump They seem to hover in place until the cut the UDP stream part of their server connection Seems like the physics is at least based on those vertices & the server side simulates physics and those physics override clientside player physics
@snake-biscuits sorry for the absence - life has been busy.
That video is interesting but does it really tell us anything we don't already know? Of course physics / collision must be checked server-side, otherwise it would be very easy for players to walk through walls and other cheats.
I've suspected that the game takes the defined vertices, and creates some collision planes out of them, as a way to save space. Has the person tried walking into the new mesh they've defined? That would be more interesting, and I suspect that they will walk right through it.
I've also been thinking it may be better to spend time looking at the UNKNOWN lumps: 41, 39, 38, 37, 20, 19, 18, 17, 16, 15.
I have found that the angel city vpk contains some different versions of the map in depot/r2pcprecert/game/r2/maps. This version has some slight differences (vertex lump included) but they’re pretty small changes
From a glance it seems mostly to be changes to some optimisation triggers but those differences could be handy for identifying some format stuff
Hey @snake-biscuits any progress on this great mystery? :stuck_out_tongue:
I’ve started work on a blender addon for viewing bsps, so far it’s been pretty helpful for understanding how everything fits together. I think can start working towards looking at loading stuff like the planes lump to see how it fits in Maybe even edit that lump to see if it affects physics in-game
I am pretty busy with uni at the moment but I will still be working on that. Did find that both titanfalls & apex have a mp_lobby map in the common .vpk, that’ll be pretty useful as it’s the smallest map in each game, though apex’s is pretty complex
This is excellent work @snake-biscuits ! I really wish I could do more but as we know reversing work can be so time consuming. What's that second screenshot? :o
I've made some progress on understanding physics in titanfall 1 & 2 this past week.
having reverse engineered about half of the PHYSICS_COLLIDE
lump, I noticed Titanfall 2 barely uses the lump
All Titanfall 2's PHYSICS_COLLIDE
lumps only use the lump for fog volumes as far as I can see.
However Titanfall 1 uses the lump just like a Source Engine .bsp
Looking at this GDC talk: https://www.youtube.com/watch?v=6BIfqfC1i7U I think they started moving towards using the Meshes / Tricoll lumps
Since Apex cuts out a lot of the CM_*
(Collision Model) lumps, I think Apex uses a combination of Meshes & the TRICOLL_*
lumps to handle physics.
Will let you know more as I investigate
Excellent work as always @snake-biscuits , I am still following you and always excited to see a GitHub email from you pop up.
Could you link to any material on TRICOLL? Does it stand for triangle collision?
Have you attempted to at least point-cloud render meshes and tricoll?
Recently we've been digging around in the Titanfall | 2: Northstar Discord Server to work out how collision meshes are stored in Titanfall 2 maps.
So far we've worked out prop physics is loaded from the props at runtime and the PHYSICS_COLLIDE lump doesn't hold as much as we think
In attempting to port some titanfall 1 maps to titanfall 2 we've encountered some ghost collidables (where props should be, but we disable props to make the map run) and some crashes that appear to happen as the result of colliding with something
One thing we have noticed is that collisions with visible geometry appears to be directly based on the position of that renderable geometry
Invisible walls (clipping brushes etc.), we haven't yet identified
Added apex_legends.BVHNode
, which might be pivotal to how physics works in Apex
Still got a bunch of new structs added by @r-ex in src/structs_r1.h
to port over to python so we can up the coverage of the Titanfall Engine & start to better map out how everything connects
In other news MRVN-radiant
is starting to get some serious use and is making for a really good testbed for building test maps to find out what works and what doesn't
Mostly brute forcing but it's still something vs. just statistical analysis
Making a lot of progress in general atm, tho mostly focused on Titanfall 2 maps rn
Amazing :) I'm still here watching from the sidelines!
Has anyone tried putting the PC versions of Apex into IDA Pro or Ghidra and find the routines for collision?
yeah we just did w/ some r5reloaded devs, haven't figured out how it all fits together yet but we can stop in the middle of a lookup
https://www.youtube.com/watch?v=1WgViRE7rmg result of returning in some collision testing function while in game
MRVN-Radiant can now make basic maps for Apex Legends w/ physics https://github.com/MRVN-Radiant/MRVN-Radiant/blob/3b89261ccb37f9baa1f0561f38db23c4cdc91035/tools/remap/source/bspfile_apex_legends.cpp#L268-L290
Haven't looked at exporting / converting to mesh of any kind just yet tho. I've yet to dig into the Apex Legends side much myself, my focus has mostly been on Titanfall 2 lately
MRVN-Radiant can now make basic maps for Apex Legends w/ physics
It can't. I just wanted to clean up the apex functions a bit so I decided to create those functions even though they dont do anything.
There's some interesting information I could share though. My current theory is this: The game walks a BVH4 tree to find out which primitives are close to the player. The nodes themselves index into a collision mask which determines who can collide with the node and its child nodes ( titan only, player only, etc. Amos pulled out the flags from apex here. I also confirmed most of them in titanfall ).
The nodes also store a child type, this can be 1 for no child, 0 for bvh node, and then 14 unknown types. From bounds checking I confirmed most of the unknown types index into a separate lump called BVH Leaf Data. The game checks if the size of the lump is divisible by 4 which suggests it's 4 bytes. Thing is I havent been able to spot a pattern and arent good enough in ida/ghidra(which just doesnt want to install) to look into the executable. I'd expect BVH Leaf Data to then index Texture Data and vertices.
One last thing regarding my collision stub. The game crashes when there's only one BVH Node with no children. It needs to index at least once into BVH Leaf Data. This makes sense as you kinda need collision to play a map.
So theoratically we need to reverse the bounds information in BVHNodes and figure out how BVHLeafData is structured and indexed.
What are "primitives" defined as here?
It's been awhile: does all this mean the geometry mesh is doubly used as a collision mesh? How does the game stop players from jumping past an invisible fence? Is it just transparent geometry?
What are "primitives" defined as here?
Titanfall uses brushes ( a convex volume defined by planes ) and tricoll ( a mesh made of vertices ) for collision. Respawn refers to these as collision primitives. We currently only generate brushes as we dont have all structs for tricoll reversed.
So in this context I'd expect each BVHNode type to define a primitive type which is then read from BVHLeafData. From looking at maps it seems respawn only use the first ~12 types.
It's been awhile: does all this mean the geometry mesh is doubly used as a collision mesh? How does the game stop players from jumping past an invisible fence? Is it just transparent geometry?
I'd expect BVHLeafData to define it's own meshes as the ones used for visuals can be quite large which is why they'd be inefficient for collision testing.
here's a couple of videos showing the (rather chaotic) visualisation of some of the BVH4 leaf data that is used for testing collision around the map: https://www.youtube.com/watch?v=APrxrT18EOs (triangles) https://www.youtube.com/watch?v=l80fKAsdUQM (quads)
triangles seem to be used for the majority of the map's geometry, whereas quads tend to be used more for buildings this is the result of hooking only 2 of the several functions responsible for parsing leaf data, so i think there is a decent amount of data that this doesn't show
It appears that some sort of basic bounding volume algorithm is used for some things like rock faces. I think this pretty much explains that they generate collision from graphical meshes and then probably tweak it after...
That makes sense, iirc Apex Legends splits VIS with static props, so they need some kind of inner volume for that (for the big rock faces anyway)
Haven't looked enough at Apex' .rmdl
to say much about how the physics model work tho, but afaik it's similar to the BVH4 system in .bsp
Haven't looked enough at Apex'
.rmdl
to say much about how the physics model work tho, but afaik it's similar to the BVH4 system in.bsp
yea, it's p much identical (same nodes, same structure of leaf data) apart from some slight differences in how data is located (bsp uses MODELS lump, rmdl has a set of offsets in a sort of "header" struct)
one notable difference that @IJARika noticed in rmdl is that the most commonly used leaf primitive types (as indicated in the node data) were different from those used in BSP. RMDL mostly used type 5 with a couple of models using 7 (haven't confirmed what either of these are yet, though i would bet that it's tris/quads respectively) BSP used a mixture of type 4 (confirmed to be tris) and type 6 (confirmed to be quads)
Did a little research in #111 bringing bsp_tool a little more up to speed w/ rexx & rika’s work
haven’t gotten too deep yet, as rn I’m working on saving edits once that’s working I can experiment in-game though I want to check out some stuff with titanfall physics first (porting tf1->2)
I'm currently trying to interact with the VPK using https://github.com/ValvePython/vpk but in my two samples, it says it's missing a magic number, and in the other it says it's invalid.
Does Apex Legends use some special VPK variant?