xenia icon indicating copy to clipboard operation
xenia copied to clipboard

[Kernel] ContentManager: add support for STFS packages

Open emoose opened this issue 4 years ago • 7 comments

(split from older PR #1250)

This PR allows ContentManager to see and mount from non-extracted STFS packages. It'll also read information from the package headers (such as display name) into the XCONTENT_DATA struct used during content enumeration (see #1407)

I also added some code to allow extracted packages to have a [filepath].headers file next to it with the StfsHeaders struct inside, so they can also have information read into XCONTENT_DATA, but I could remove this part from the PR if desired.

(edit: not sure why travis build failed, is there a way to retry it?)

emoose avatar Jul 23 '19 07:07 emoose

Had a try at making ContentPackage a base class which StfsContentPackage & FolderContentPackage inherit from, the code seems to work fine, with both package types loading in mixed-together without issue.

Also changed how the packages are managed a little, instead of ContentManager holding a std::map of root_path -> package pairs, it's now a vector of packages, with each containing their own root_path vectors instead.

This should let a single package be mounted under multiple root paths (in case that's ever needed), with the ContentPackage instance also handling the symlinking/desymlinking for each path.

emoose avatar Jul 23 '19 16:07 emoose

Been working on a rewrite of the STFS structures, changing them from classes into structs & using things like xe::be so that they'll work just like the other X360 structs we use in Xenia (without needing any StfsHeader::Read/StfsHeader::Write functions), so now we can just cast a pointer to them, copy the memory of them directly, etc..

Also included a few header structures we were missing like the Installer struct, which is used on title update packages to specify some info about the title being patched, along with a couple other ones.

Wasn't sure about adding it to this PR though since it seems this might need some changes already, so I've put that rewrite into another branch for now: https://github.com/emoose/xenia/commits/stfs-headers

(there's commits there that probably need to be squashed, and some that probably should be broken up... I'll look into fixing all that once I've got everything working there as expected)

Still need to test it and make sure I haven't broken anything, it should be working fine though hopefully. (edit: loading from STFS still works fine, haven't tested SVOD as I don't have any SVOD files to try with, would appreciate if someone could try it out with one!)

emoose avatar Aug 24 '19 01:08 emoose

Unfortunately I didn't have a SVOD to try with, but I did merge your changes with the master on a local repo and didn't notice any ill effects. In fact, LEGO Rock Band was able to properly read (and write) the game data (via XamUserReadProfileSettings), whereas I think I was having issues with it before. The common storage issue I see in the logs for the games I test with is RtlNtStatusToDosError 103 => 3E5, which I've noted before.

TranzRail avatar Aug 24 '19 02:08 TranzRail

Added some code in stfs-headers to make ContentManager::CreateContent write the saves display name/content type out to a headers.bin file, this should now allow games like Kameo & Halo 3 to recognise their own save games! (also rebased that branch to latest master too, but seems like travis has a problem with the STFS structs packing though.. gonna have to look into that soon, good thing I put that stuff in a different branch :)

@TranzRail good to hear, interesting that it helped with XamUserReadProfileSettings, don't think this should touch any of that, guess that maybe it needed to do something save/STFS related for the profile settings stuff to work properly, or something like that.

The RtlNtStatusToDosError messages seem pretty common, looks like a lot of games try to access files that don't exist, think in most cases it isn't really a fault with Xenia, probably more a fault with lazy devs :P

emoose avatar Aug 24 '19 02:08 emoose

@emoose The error in question is ERROR_IO_PENDING (Overlapped I/O operation is in progress) when trying to write/save. So I doubt that'll be because of lazy devs, given how common it is?

The XamUserReadProfileSettings I think could do with a revamp at some point. Have it more structured.

It's possible that in some cases, some games will be looking for a particular mount that does not exist. I don't know how it currently works, but I imagine we'd want to setup our own static mounts for things that would exist when dash.xex is booted for instance (for things like internal storage, optical drive, flash, USB, etc) and then we can middle manage them between the exported functions.

TranzRail avatar Aug 24 '19 03:08 TranzRail

@emoose just tested Dead Space 1 with https://github.com/emoose/xenia/commit/7e2a163a51836be07d54959aee134a32b7ffd169 in SVOD and it loaded fine

illusion0001 avatar Aug 29 '19 12:08 illusion0001

Saw this mentioned on twitter, I started another STFS branch at https://github.com/emoose/xenia/commits/stfs-improvements a little while ago, mostly just improvements for STFS structs & some fixes for CON packages (atm it looks like current code doesn't work with them), a lot less involved than this PR, will try PRing it soon.

I'm not sure if the method used in this PR with different StfsContentPackage/FolderContentPackage classes is really that ideal anymore, maybe it'd be better to have the ContentPackage class use StfsContainerDevice, let that device handle the STFS header stuff for us, but also let it create/own a HostPathDevice itself for folder packages if needed, that way all folder packages will have STFS headers handled for them (for any XamContent stuff that need to access them), and would also let both folders + packages use mostly the same code.

I think StfsContainerDevice owning a HostPathDevice might be the best/only(?) way to allow loading in CON-packaged saves/profiles while also letting changes be written back to disk too, unless someone wants to try adding write support to the STFS code... not really a fan of writing things to binary blobs that need tools to access though. (a quick test showed something like this can work pretty easily too, just needed to let StfsContainerDevice::ResolvePath call into the child HostPathDevice::ResolvePath if it's being used - still needs an extraction step beforehand though, but CONs are usually pretty small so not a big deal)

Made a PoC of the HostPathDevice changes here: https://github.com/emoose/xenia/commits/stfs-folders, not much actually needed changing it seems, commit msgs talk a bit about what changed, I'll write some more about that in the stfs-improvements PR.

emoose avatar Apr 29 '21 08:04 emoose