Replace a movzx after setae in both ComputeMemoryAddressOffset and ComputeMemoryAddress with a xor_ of eax prior to the cmp. This reduces the length in bytes of both sequences by 1, and should be a moderate ICache usage reduction thanks to the frequency of these sequences.
Couldn't find a way to get bitfields & byte-swapping to play well together, so this was the best I could come up with... at least the proper version numbers will show in the log file now :)
Happy new year! Here's my first commit of the 2020s :)
With these fixes, Halo 3 Epsilon will now write cached map data & other things (autosaves/datamine...) to the cache0/cache1 partitions, (as long as mount_cache cvar is set)
(Halo 3 retail will also write some things to cache with this, but oddly doesn't cache map stuff... which is strange because Epsilon was built only a day or two after the retail build, so I'm not sure why it'd work differently...
Maybe retail needs a TU applied for it to work or something like that)
Other games should hopefully work with cache now too (AFAIK the problem was in SDK library code, that a lot of games probably share)
No idea if this will actually improve anything though, but at least things will work closer to what games expect :)
The way this works is by tricking the cache-partition code (staticly linked into the game exe) into thinking that the Partition0/Cache0/Cache1 devices are valid.
To do that I made another kind of VFS device, the NullDevice, which just takes in a list of paths to handle.
Whenever an IO request is made to one of these paths, the NullDevice can simply pretend to the game that everything was successful, which satisfies the requirements needed for caching.
It also makes use of another trick: setting TitleInsecureCacheDrive XEX permission, which seems to skip a huge chunk of cache-init code (STFC filesystem device registration & stuff like that)
I'm not sure if this would work with every single revision of the STFC/cache code though...
At least in Halo 3 the retail code will handle the TitleInsecureCacheDrive case for us fine, but maybe older/more recent versions don't include functionality for it, need to look into it some more.
(I did try an impl. without needing this permission months ago, got pretty far with it but got caught on one tiny issue that I couldn't figure out... too bad I didn't find out about this permission earlier!)
This adds more mount paths for the XEX's local directory to Emulator::LaunchXexFile, so any XEXs that try to use these mountpoints can load files from the XEX directory.
Mount points added:
- \Device\Harddisk0\Partition0 - original mountpoint used by Xenia
- \Device\Harddisk0\Partition1 - some games/apps seem to use this to refer to HDD1:
- \Device\Harddisk0\Partition1\DEVKIT
Used by xshell.xex, gets linked as E: (aka "development drive")
Even if a DEVKIT folder exists inside the local folder, it seems we still have to add this mount point explicitly.
- \Device\LauncherData
Also used by xshell.xex for various UI resources
The xlaunch.fdf file is normally mounted via DmMountFdfxVolume to this path (xlaunch.fdf is a FATX formatted container)
By mounting this xshell can retrieve extracted resources from the local dir.
- \SystemRoot
Normally refers to the NAND, used by dash.xex to retrieve XZP resources when they aren't inside xam.xex.
Other apps also use this to refer to other system XEXs/resources
By mounting it we can just place any needed resources in the local dir.
PVR stores the processor/motherboard revision, the latest I could find seems to be 0x710800 which is probably a Corona.
XShell tries to retrieve this during launch to print it on the console (search "XSHELL: CPUPVR" on pastebin for some examples)
Xenia crashes because it's unimplemented, so I just made it return 0x710800. It could be worth moving this to be a constant somewhere though.
IIRC hypervisor/kernel uses this for some things too, but since we don't emulate those it's not much of a problem, but there could still be other XEXs which use it for something.
This just adds some extra XConfig settings that the dashboard tries to retrieve.
The XCONFIG_USER_RETAIL_FLAGS setting gets used to decide whether to show the initial setup/OOBE wizard or not.
Since the OOBE currently isn't usable in Xenia (mostly due to missing XamProfile* exports, afaik), this setting is by default set to skip it.
But if that isn't desired the --xconfig_initial_setup flag can be used to un-set it.
This uses ContentManager to look for title updates, updates should be inside Content\[TitleID]\000B0000\
The updates can either be made up of an STFS package, or a folder containing extracted update files.
The update will then be mounted under update:\, so games that rely on loading updated assets from the TU should also work with it.
Normally ContentManager resolves package paths by using kernel_state_->title_id() as the title ID, but if we want to use ContentManager for TU's that won't work, since the XEX won't be fully loaded into kernel_state_->executable_module_ yet.
We can get around this by allowing the title ID used by ContentManager to be overridden, this should also help us support games that load packages from other title IDs.
This is fixed by adding a new startup_type parameter to XThread, which
lets us create an XThread that can run DllMain with correct arguments.
LaunchModule is then modified to use that param when launching a DLL
module that has an entrypoint. UserModule::LoadXexContinue also has code
added to call SetExecutableModule prior to loading any import libraries