Jump to content
mrsrt

Animation Limit Crash Fix

Recommended Posts

Animation Limit Crash Fix

View File

SSE version released

 

About

37f0ecd0a870ecb53b586965dc6d.png

The patch fixes the crash on game loading when you install too many animations with FNIS. The one mentioned in the article by Fore. May also give you increased fps and loading speed by skipping a redundant part of code. More technical information you can find in the Developers section below.

 

Requirements

- SKSE 

- (SSE only) Supported runtime versions*: 1.5.73, 1.5.80, 1.5.97. Others can be supported too, but wasn't tested. It's safe to try, you'll get an appropriate message in case of incompatibility.

 

Installation

Just copy the dll to Data/SKSE/Plugins

 

Recommended

Continue Game No Crash (LE) or analogs to fix FootIK error

CrashFixPlugin (LE) for other stability patches

EnbSeries for additional memory patches

You can also check my topic for additional fixes and information related to game stability for LE version of the game.

 

Incompatibility

Animation Loading Fix [LE only] - does the same job and (since ver 1.1) edits the same instruction. This solution does not skip, but doubles the existen limit, also preload animations what helps to skip FootIK error. Version 1.0 is compatible.

SSE Engine Fixes [SSE only] - has the same change to the patching instruction as Animation Loading Fix v1.1 for LE. To make it compatible you need to disable AnimationLoadSignedCrash option in EngineFixes.ini file. 

 

Notes
- There're several limits related to animations, this article will help you to understand them.
- If you want to know more about performance impact by the patch, you can find more info in the article.

- The patch successfully passed the beta test with several thousands of downloads with no negative feedback (LE version), however, side effects not yet completely discovered. If you find something weird and you sure that it's related to the patch, please, inform me and other users with a post in the topic. 

 

F.A.Q.

Q: I'm getting "Invalid segment" error on game startup, what should I do?

A: It means to the place, that should be patched by the plugin, changes was already made. Please, check the compatbility section.

 

Q: I'm getting CTD on loading / My game doesn't load after installation, what should I do?

A: Highly likely it's caused by incompatibility. Please, check the compatbility section and be sure you're using the latest version of the patch.

 

Q: Will the patch really give me a performance boost?

A: The question was very detailed explained here: https://www.nexusmods.com/skyrim/articles/52477

 

Q: How to understand do I need the patch or not?

A: If you have installed several thousands of animations another bunch of new anims may break your game in a state where you'll always get CTD on loading or starting a new game. In that case the patch will help you to cure the CTD. If you have no installed animations by FNIS you can try the patch just for performance purpose.

 

Q: What's the difference between the patch and SSE Engine Fixes (SSE) or Animation Loading Fix v1.1 (LE)?

A: SSE Engine Fixes and Animation Loading Fix (since v1.1) changes movsx -> movzx instruction, what doubles the existen limit of numStaticNodes. A crash or unpredicted behavior still may happen when you will have more than 65535 numStaticNodes (instead of 32767) using the Engine Fixes or Animation Loading Fix solution.
This patch always put 0 instead of incorrect value to the numStaticNodes register, what always help to cure the CTD and frees CPU from additional work.

 

Q: (SSE) I'm getting "does not appear to be an SKSE plugin" message in skse64.log, is it okay?

A: Yes, it's okay, just ignore it. The message notifies that the plugin was loaded not through SKSE64 API, but classical way with dllmain. I didn't find yet a proper solution to attach the plugin through classical SKSE API for 64-bit version.

 

Q: (SSE) Will the patch work with 1.5.XX runtime version?

A: I have personally tested its work on 1.5.73, 1.5.80 and 1.5.97 versions, everything works good. If you have a different runtime version you can just try it, it's safe. In case of incompatibility you'll get an appropriate message.

 

Q: But the limit still exists in FNIS?

A: Please, check the article for better understanding of animation limits: https://www.nexusmods.com/skyrim/articles/52476

 

Permission

Contact me for permission if you want to reupload the fix somewhere or want to include it in your project.

 

For Developers

If you're interesting in the technical part of the fix here you can find useful information: 

Reverse info for LE version

Render impact finding

Animation affection tests

SSE Reverse info

 

Updates

25-Dec-2019

(SSE Only) Pattern matching added. Now it should be compatible with any SKSE and runtime version, including future official patches (unless Bethesda will do their own changes to the patching segment).

 

23-Dec-2019

Added segment checking for both LE and SSE. Now it's safe to use with any SKSE and runtime version. If something incompatible you'll get an appropriate message.

 

21-Dec-2019

SSE version released

 

8-Dec-2019

No internal changes in the mod. Restructured download archive, for comfortable installation with mod managers. Source file now in a separated download.


  • Submitter
  • Submitted
    12/07/2019
  • Category
  • Requires
    SKSE
  • Special Edition Compatible
    Yes

 

Share this post


Link to post
50 minutes ago, MadMansGun said:

so how dose this compare to this? :

https://www.nexusmods.com/skyrim/mods/98204?

It should work together

UPD: tested, seems conflict. Need to take some simple preloader like Continue Game No Crash just for FootIK

UPD2: completely incompatible with this one due to editing the same instruction.

UPD3: added incompatibility section

 

In the compared mod the limit still exists, but doubled. I believe with my fix the only limit left is that Fore sets in FNIS. 

UPD4: version 1.0 is compatible

Share this post


Link to post
1 hour ago, mrsrt said:

It should work together

UPD: tested, seems conflict. Need to take some simple preloader like Continue Game No Crash just for FootIK

UPD2: completely incompatible with this one due to editing the same instruction.

UPD3: added incompatibility section

 

In the compared mod the limit still exists, but doubled. I believe with my fix the only limit left is that Fore sets in FNIS. 

UPD4: version 1.0 is compatible

😱

Share this post


Link to post

Then does this extends the limit to the amount that fore has extended in FNIS. Is this what you are saying ?

 

That would be great. :)

 

I am just wanting to understand the limits, as to how much it will help over all. I do wish like most to be unhindered by the Skyrim animation limit, but we still have some what of a usable memory limit even with ENB as a booster to that.

 

  I have used the other limit extender though, but I have tried not to push its limits any more than needed. Just sort of curious about the whole effects gained, and of course the repercussions that using it might cause.

 

By the way a wonderful thing, Thank you for it very much!

Share this post


Link to post

Wow, this is wonderful (if it really works without problems, time and more people testing it will show) - this fixes the last big annoyance in Skyrim, that people have complained about ever since SL came out.

No more animation limit, no more editing the SLAL packs and removing some animations to stay under the CTD limit.

Great work!!!

 

Once again, people fix what Bethesda fucked up ;)

 

Mods: This needs to be pinned in the downloads section - everyone should see this!

Share this post


Link to post
1 hour ago, oldgrumbler said:

author, in  https://www.nexusmods.com/skyrim/mods/98204 present source code. u can read/compare and then understand- no need to invent the bicycle with one wheel... 

I didn't see the mod before coz I thought it's a simple preloader and has no reloation to the limit. It was like this, but since ver 1.1 the author changes MOVSX to MOVZX in the instruction where short registry access and gets unsigned short, what doubles the limit. My solution is to completely drop the initializing register with XOR to skip problematic place. Actually, these mods can be merged or used together with v1.0.

The skipped loop seems to be some block cleaner which hasn't important affection on the game process, because data in there will be overwritten btw. I shared my solution to get feedback. If it will pass the beta stage, probably i'll contact the author of Animation Loading Fix to merge our solutions or I'll do something myself just for FootIK error. 

Share this post


Link to post
9 hours ago, galgat said:

Then does this extends the limit to the amount that fore has extended in FNIS. Is this what you are saying ?

As I understand, Fore did some restrictions and optimizations with registry to prevent passing the internal game limit. Now the limit is skipped, so, if my solution will pass beta, probably Fore can completely remove or largely increase his limit in FNIS. It will need some tests ofc, but for now need to listen feedback at least for 2 weeks if my decision to skip code was really safe. 

8 hours ago, AnInsaneMoose said:

Please release this for SSE with the latest SKSE

Sorry, but I have no ready SSE setup to do that right now. Maybe later.

3 hours ago, WolfKent said:

Pls make like this folders for comfort MO2 install. 

Done

Share this post


Link to post

Just for people understanding.

 

There're several limits related to animations:

1. FNIS limit - the first one which player will meet if installed too much animations. Fore increases the limit each release of XXL version of his priceless tool. As for now XXL version limited to max 26162 animations. On that limit I can't affect, Fore sets it himself in his tool. 

 

2. FootIK limit - when we initailly loading a gamesave with too much animations there's a chance to get FootIK startup error. The error can be skipped with gamesave preloaders like Continue Game No Crash, Load Game CTD Fix or with animations preloader in Animation Loading Fix. 

 

3. Register limit - the game has internal limit of some objects related to animations - 32768. When we pass the limit we get 0xBE6DD3 CTD. This fix was created to avoid exactly that limit.

 

4. SexLab limit - the maximum amount of animations the framework can store in its registry. This limit related only to the framework. ZaZ, DD, TKDodge and other non-sexlab animations has no affection on the limit. Can be expanded with a tweak shared somewhere on LL, results in longer animation search due to bigger iteration subject. 

 

5. Memory limit - animations, as game-objects commit some space in the main memory block (block 1). There're many tests and words was written related to this, the only thing you should know, when the block overflow crash happens. You can adjust the size of the block with DefaultHeapInitialAllocMB option in SKSE.ini, or you can try to enable UseOSAllocators in CrashFixPlugin.ini, which split the block data in shared memory. I also recommend to use ReduceSystemMemoryUsage in enblocal.ini to free process memory from texture data. 

Note that:

- If you set DefaultHeapInitialAllocMB more than 768 the ExpandSystemMemoryX64 option in enblocal.ini must be disabled.

- If you enable UseOSAllocators the game become much more sensitive to game files correctness, what may bring additional random crashes if something wrong. 

Share this post


Link to post

yes you did it you ingenious bastards :D if this works that means the one problem i consistently run into causing me to reinstall skyrim is now pretty much fixed with this

footik is easy to solve and circumvent thanks for making this if it works then this is another step into the technological advancement of this game 

you are the type of people why i still play this game this is amazing :) 

Share this post


Link to post
1 hour ago, mrsrt said:

.

4. SexLab's limit on animation sets (not related to what your fixing here but it's still a limit that people keep overlooking)

Share this post


Link to post
45 minutes ago, MadMansGun said:

4. SexLab's limit on animation sets (not related to what your fixing here but it's still a limit that people keep overlooking)

Edited, thank you

Share this post


Link to post
1 hour ago, MadMansGun said:

4. SexLab's limit on animation sets (not related to what your fixing here but it's still a limit that people keep overlooking)

Osmel integrated the Sexlab 1.63 - 750 animation fix in his patch. (Sexlab Utility Plus)

To date it works flawlessly. But I want to make an extreme test and stretch it to the limit and see.

 

Share this post


Link to post
56 minutes ago, Nymra said:

Osmel integrated the Sexlab 1.63 - 750 animation fix in his patch

is that one working any better then the old one?, the old "more SL animation" mod would say 750 but it would not actually register the animations.

Share this post


Link to post
23 hours ago, mrsrt said:

[Beta] LE Animation Limit Crash Fix

View File


37f0ecd0a870ecb53b586965dc6d.png

 

About

The patch fixes 0xBE6DD3 crash that happens when you install too much animations. The CTD happens because of short register overflow, what leads to incorrect memory access that crash the game (Additional technical information can be found in the included source file). The patch skips the code where the problem occurs. Consequences not yet discovered, but initial tests with the setup on screenshot above behave very good. It also increases loading speed a bit due to the skip.

 

 

Congratulations, mrsrt, for a great finding. Whatever the result of your plugin might be in the end.

 

When I first read your description I was VERY skeptical. Why should a software team that is by no means known to make one statement too much especially when it comes to error checking, have code in their system that is regularly executed, but can simply be removed? On second thought I have a THEORY now why this very well can be in this case.

The interface that Havok provides is not sufficient for Skyrim. Therefore there are a couple of files (meshes/animation(set)datasinglefile.txt). These files contain information from the behavior files which have been created during Beth's game creation process. And they are really needed. Because when FNIS adds certain types of files (e.g. attack) A(S)DSF have to be manipulated as well.

 

But the process which leads to the Animation Load CTD uses information which comes in part directly from the custom behavior files during game start. Information which is NOT part of the A(S)DSF.txt files. I have asked myself repeatedly, why would Beth use 2 different methods to get to the same kind of information. Information which even overlaps in part.

 

The reason might be very simple. In the beginning they read everything they needed directly for the behavior files. But over time they needed more and more information that way, and so they decided to extract the necessary data in an pre-processing step. And while they removed the old code for 1st person and creatures during transition, they simply forgot to remove it for 3rd person. And this UNNECESSARY code is causing the Animation Load CTD as of today.

 

As I said: a theory. But with your finding there is enough evidence now to make it look very possible. Maybe you could prove it by not only deactivating the current path you have. But maybe even deeper in the call stack. And it also could noticably reduce the game starting time. It's really worth trying. In any case, I really look forward to the test results of the users.

Share this post


Link to post
20 minutes ago, fore said:

Congratulations, mrsrt, for a great finding. Whatever the result of your plugin might be in the end.

Thank you. 

 

20 minutes ago, fore said:

As I said: a theory. But with your finding there is enough evidence now to make it look very possible. Maybe you could prove it by not only deactivating the current path you have. But maybe even deeper in the call stack. And it also could noticably reduce the game starting time. It's really worth trying. In any case, I really look forward to the test results of the users.

Well, I can provide the reverse info during the research. 

Spoiler

At first, let's take a look at the code where the exception happens:

c0b9255cd7fc305c18917df4a696.png

 

On line 27 here the function tries to write 0 accessing v5 pointer. This pointer increases each iteration until v4 variable is not 0, which also decreases each iteration. In other words this loop cleans up some memory data, I guess it's a memory block or array due to the consistent access. If v4 variable is incorrect the code tries to write wrong addresses what eventually lead to segmentation fault that crashes the game process. 

This variable comes here as the a2 argument from sub_BE6C50 function:

7c0c3d9090ddb619b923fbc99d73.png

 

Line 32. Pseudocode here a bit messed up, but I think it's better than to provide raw assembler. The first argument is a class-object link, the second arg is getting by complex operation with regiser casting, but what's important here is the initial accessing to the actual value:

00BE6CB7     0FBF86 A800000>MOVSX EAX,WORD PTR DS:[ESI+A8]

Access again happens by pointer with static offset, what possibly say that the value is stored in some block too. Also we see that firstly the value is writing in a 2-byte (short) register. This is our bottleneck. After that due to DS registry overflow its value becomes negative what leads to absolutely incorrect values after final cast (like over 2 billions) due to cast operation mechanic with signed values. In result when we come to the loop I shown above with that value we simply crash. My solution is to give the function 0 instead of incorrect value.

 

So, what consequences it may bring? We don't actually know for sure what exactly is stored in the block/array which the loop tries to clear. It is not a static variable in code but dynamic data in a block with pointer+offset accessing. It will be quite hard to say what exactly the block stores without source code and much more hard to say what it may bring. However, we know what the function does is a clearing with simply writing 0. It is not a usage of realloc() or free(), which have important relation to the process memory, it's a simple "logical" clean up, with no changes to the actual memory block. 

I have 3 guesses related to this:

1) It has a logical purpose to mark the block for further reuse and the pointers store some kind of flags. In that case, we may lose a bit of memory. 

2) Logical cleaning but without flags. Simple nullification of the block before future usage. If so, there're absolutely no noticable consequences, new values just overwrite old ones. In that case the function is redundant and I think this is the most likely option.

3) Maybe to one of Beth developers came a perfect idea instead of free() the block to nullify it, lol. Who knows, shit happens, I saw much worse things. 

 

What can I say for sure:

- The problematic function has no calls from other places.

- It's calling at the end of gamesave loading as other clean ups and never before it (no main menu or engine loading calls). Didn't test loadings between cells but I guess there possible too.

- There're several calls in a row (more than 10) with different values during gamesave loading, if you're interested I can catch values with debugger.

Share this post


Link to post
2 hours ago, mrsrt said:

Thank you. 

 

Well, I can provide the reverse info during the research. 

  Reveal hidden contents

 

So, what consequences it may bring? We don't actually know for sure what exactly is stored in the block/array which the loop tries to clear. It is not a static variable in code but dynamic data in a block with pointer+offset accessing. It will be quite hard to say what exactly the block stores without source code and much more hard to say what it may bring. However, we know what the function does is a clearing with simply writing 0. It is not a usage of realloc() or free(), which have important relation to the process memory, it's a simple "logical" clean up, with no changes to the actual memory block. 

I have 3 guesses related to this:

1) It has a logical purpose to mark the block for further reuse and the pointers store some kind of flags. In that case, we may lose a bit of memory. 

2) Logical cleaning but without flags. Simple nullification of the block before future usage. If so, there're absolutely no noticable consequences, new values just overwrite old ones. In that case the function is redundant and I think this is the most likely option.

3) Maybe to one of Beth developers came a perfect idea instead of free() the block to nullify it, lol. Who knows, shit happens, I saw much worse things. 

 

What can I say for sure:

- The problematic function has no calls from other places.

- It's calling at the end of gamesave loading as other clean ups and never before it (no main menu or engine loading calls). Didn't test loadings between cells but I guess there possible too.

- There're several calls in a row (more than 10) with different values during gamesave loading, if you're interested I can catch values with debugger.

 

That it seems to be part of the clean ups does surprise me a bit. Because CTD is always right at the calculated point. Which means there must have been some activities way before that which have determined which data has to be stored. And usually I would expect at that time the data was not only calculated, but also stored. Why did the overflow not happen at that time? That could also mean that the game still collects the data. But does the collection with proper register size.

 

More than 10 calls? Maybe 15 or 16? 18 is the number of all 3rd person behavior files. But I found out that all changes made mag movement and magcast movement didn't have any impact on the animation limit (first time I had doubts that this CTD causing code didn't what it was supposedly made for).

 

I would like to look into dumps, but I'm not sure if I can really understand something. Maybe something based on any string values. Or some crc value patterns, like they are used today in the ASDSF files.

 

Share this post


Link to post
12 hours ago, fore said:

...

I continued the research and found very interesting details.

At first, take a look at the values I got during the gamesave loading:

Spoiler

0000000D
0000000D
00000007
00000007
00000005
00000005
00000007
00000007
00000007
00000007
000019CB <- the bottleneck value
000019CB
00001045
00001045
0000000D
0000000D
000019CB
00001045
0000000D
0000000D
0000000D
000019CB
0000000D
0000000D
00000007
00000007
00000007
0000000D
00000005
0000000D
000019CB
00000005
00000005
00000005
000019CB
00000005
00000005
00000005
000019CB
000019CB
000019CB
/RENDER STARTED/
000019CB
000019CB
000019CB
000019CB
000019CB
000019CB
000019CB
000019CB
000019CB
...

 

- At the beginning they duplicate twice, it looks like a cleanup after processing paired data (gender?).

- At line 11 you see the first call with 000019CB, this is the value which increases with player animations, 6603 in decimal for me if I remove character's animations and behavior (simple folders rename, no FNIS recall, just to not crash while debugging the non-patched game).

- But what's much more interesting here is the continuation of calling the func with player data AFTER render started. The call happens together with frame rendering, possibly each frame. Never happens while in pause or in other render-stopped states. 

- Spawning 5 horses near player in qasmoke results in 6 calls per frame:

000019CB
000000D8
000000D8
000000D8
000000D8
000000D8

- Werewolf transformation of player doesn't change anything

 

These results may say that if we really can safely skip the part of code we aren't just fixing the CTD and increasing loading speed, but also boosting up FPS and overall game performance. 

 

14 hours ago, fore said:

I would like to look into dumps, but I'm not sure if I can really understand something. Maybe something based on any string values. Or some crc value patterns, like they are used today in the ASDSF files.

Unfortunatelly, strings stored as char arrays in memory, so you'll not see any text in the dump. However, if you want to give it a try I attached the block the loop tries to clear. The first pointer points at 35610108, player's counter is 19CB, so the last pointer should be at 35614E69 (each itr +3). 

dmp.TXT

Share this post


Link to post

If this actually works without huge bugs this is probably the best new skyrim mod that came out this year on this site. Too bad i don't play LE anymore i wish a mod like this came to SE

Share this post


Link to post

Can confirm this works, for me.

Threw on everything I had, cept ZAZ 8.0, which is in the next test. Booting was SLOW, but it didn't CTD when I buried it in animations. So hooray!
10,000% endorsement. Holy hell this lets me go back to using Devious Devices willy-nilly. God Bless, my friend. You made me happy, this day.

 

A+.

Share this post


Link to post

I've had time today (I took early vacation for christmas this year due to an increased amount of stress) and started a new game with this and ~124% animation CTD (according to FNIS) and was able to play for 6 hours (with taking breaks to eat and get some fresh air - but not shutting down the game even once) without one crash (i could do that before too but not with that many animations).

I also tested all mods that i have which are the usual suspects:

Overhauls, ETAC, Immersive stuff, Combat mods, Followers, Defeat, SL Adventures, DD, ZAZ 8, Survival, Solutions, many SOS addons, Estrus, SLEN, Approach, etc etc

I have over 400 esps in my load order merged into 237 and so far i have not encountered a bug breaking any functionality.

I think its safe to use at this point.

Also loading times are super fast right now (M2-SSD).

 

Mods: Pin it in the downloads section?

Share this post


Link to post

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

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...