Jump to content

[LW] Increasing Function size?


Kaldreth88

Recommended Posts

I've been looking into changing how the game flags special soldiers and I found the function XGStrategySoldier.IsASpecialSoldier in XComStrategyGame.upk. I understand how it flags Zhang, Annette, and Van Doorn so I don't want to change that. What I would like to do is add another condition that flags the Easter Egg heroes as special soldiers, too. There just doesn't seem to be enough space left for that. I noticed this function in Long War is bigger compared to the vanilla function. How do I go about increasing the size of the function, and what are some practices to determine the correct byte and virtual memory size? From reading through the forums, I have a vague understanding of how this is done. The wiki doesn't provide enough information on how this works or what the downsides are.

 

In XGStrategySoldier.IsASuperSoldier , m_eEasterEggChar has the values for each Super Soldier. I rewrote that function so it doesn't flag the easter egg heroes as super soldiers. I figured in XGStrategySoldier.IsASpecialSoldier I would just add a line that states if m_eEasterEggChar is greater than 0 it would should be a Special Soldier. I haven't figured out exactly how I'll write that script out since I'm still learning how unreal script works, but I'll get around to it.

 

If there's an alternative (easier) way to go about this, I wouldn't mind doing that instead. Thanks in advance.

Link to comment
Share on other sites

OK. So there are different ways to resize an object in Patcher, all of them are described in PatchUPK_Readme.txt.

 

It is preferable to use AUTO modifier to make Patcher automatically check ans resize the object if necessary. Example:

OBJECT=XGStrategyAI.GetAltWeapon:AUTO
If you are using pseudo-code auto resize will adjust both serial and memory sizes for you, but if you are using hex, it will adjust serial size only and you'll need to calculate and set memory size manually.

 

If you are rewriting the whole function and using pseudo-code the best way is to use AUTO modifier and [REPLACEMENT_CODE] section. In this case Patcher will resize the function to fit replacement code size and adjust all the sizes.

 

Another way to resize a function is to use EXPAND_FUNCTION key:

EXPAND_FUNCTION=XGStrategyAI.GetPossibleAliens:5828
5828 here is the size of the whole function object, not just the script. Edited by wghost81
Link to comment
Share on other sites

That's a lot of information. I'm at a loss on where to go from here. Pseudo-code seems to be the easiest way but I don't know how it works, and I don't want to rewrite the entire function. I'm only looking to insert a line and expanding the function size. If that involves rewriting the entire function in psuedo-code that sounds impossible to me, at the moment.

 

I'd probably have an easier time testing out my changes in hex code, but I still don't understand how I "set memory size manually". And how do I calculate the memory size of the original and the modified version?

is it by adding this line to the file?

 

EXPAND_FUNCTION=XGStrategyAI.GetPossibleAliens:5828

Link to comment
Share on other sites

It depends on the function and the code. If there are jump offsets, for example, you'll need to re-calculate them because the newly inserted code will shift serial and memory positions.

 

Can you post the unreal or hex code here? So I could see what will be the easiest way in your case.

 

Here's the similar question about memory size I answered recently: http://forums.nexusmods.com/index.php?/topic/2686094-my-mod-looks-right-when-decompiled-with-ue-explorer-but-it-crashes-the-game-on-start-up/?p=23578279

Link to comment
Share on other sites

Here it is from XcomStrategygame.upk>XGStrategySoldier.IsASpecialSoldier

 

 

(000/000) [0F 00 C6 53 00 00 21 16 36 00 00 00 00 00 00]
L(19/15) -> LV(9/5) -> NC(9/9)
nmZhang = 'ZhangSoldier'

(013/00F) [0F 00 C5 53 00 00 21 44 01 00 00 00 00 00 00]
L(19/15) -> LV(9/5) -> NC(9/9)
nmAnnette = 'Annette'

(026/01E) [07 50 01 84 9A 35 07 FB FF FF B1 F9 FF FF 00 00 35 BC F8 FF FF A5 F9 FF FF 00 00 01 60 53 00 00 19 2E 58 FE FF FF 19 12 20 C6 FE FF FF 0A 00 8E FA FF FF 00 1C 3D FD FF FF 16 0A 00 90 FA FF FF 00 1B 8D 11 00 00 00 00 00 00 16 15 00 C2 FB FF FF 00 1C A8 FC FF FF 24 04 00 C6 53 00 00 16 16 18 91 00 9A 35 07 FB FF FF B1 F9 FF FF 00 00 35 BC F8 FF FF A5 F9 FF FF 00 00 01 60 53 00 00 19 2E 58 FE FF FF 19 12 20 C6 FE FF FF 0A 00 8E FA FF FF 00 1C 3D FD FF FF 16 0A 00 90 FA FF FF 00 1B 8D 11 00 00 00 00 00 00 16 15 00 C2 FB FF FF 00 1C A8 FC FF FF 24 04 00 C5 53 00 00 16 16 16]
JIN(296/192) -> NF(293/189) -> NF(144/92) -> SM(47/27) -> SM(28/16) -> IV(9/5) -> C(95/63) -> CDC(62/42) -> C(53/37) -> CC(31/19) -> OC(9/5) -> FF(10/6) -> EFP(1/1) -> VF(10/10) -> EFP(1/1) -> FF(21/13) -> BC(2/2) -> LV(9/5) -> EFP(1/1) -> EFP(1/1) -> S(147/95) -> NF(144/92) -> SM(47/27) -> SM(28/16) -> IV(9/5) -> C(95/63) -> CDC(62/42) -> C(53/37) -> CC(31/19) -> OC(9/5) -> FF(10/6) -> EFP(1/1) -> VF(10/10) -> EFP(1/1) -> FF(21/13) -> BC(2/2) -> LV(9/5) -> EFP(1/1) -> EFP(1/1) -> EFP(1/1)
if((m_kSoldier.kAppearance.iHead == XComContentManager(class'Engine'.static.GetEngine().GetContentManager()).GetContentIdFromTag(4, nmZhang)) || m_kSoldier.kAppearance.iHead == XComContentManager(class'Engine'.static.GetEngine().GetContentManager()).GetContentIdFromTag(4, nmAnnette))

(14E/0DE) [04 27]
R(2/2) -> T(1/1)
return true

(150/0E0) [07 80 01 7A 35 F0 F8 FF FF A5 F9 FF FF 00 01 01 60 53 00 00 1F 54 68 65 20 47 65 6E 65 72 61 6C 00 16]
JIN(46/34) -> NF(43/31) -> SM(28/16) -> IV(9/5) -> SC(13/13) -> EFP(1/1)
if(m_kSoldier.strNickName == "The General")

(17E/102) [04 27]
R(2/2) -> T(1/1)
return true

(180/104) [04 28]
R(2/2) -> F(1/1)
return false

(182/106) [04 3A C7 53 00 00]
R(10/6) -> RN(9/5)
return ReturnValue

(18C/10C) [53]
EOS(1/1)

 

 

I'm reading through that post, atm. It's making more sense.

Edited by Kaldreth88
Link to comment
Share on other sites

That's the original LW code, as far as I can see. It would be better if I could see the modified one. :wink:

 

But regardless, as you wrote earlier, you're trying to add some code here. If adding it to the end of the function is OK, you can try using before/after style:

OBJECT=XGStrategySoldier.IsASpecialSoldier:AUTO
[BEFORE_CODE]
04 27
04 28
04 3A <.ReturnValue>
[AFTER_CODE]
04 27
//fit your new code here
//if you use pseudo-code, patcher will recalculate both memory and serial sizes automatically
//but since you are inserting a code, not rewriting a whole script,
//you still need to calculate all the jump offsets in your code manually (use UEE tokens view for help)
//no recalculations are needed for original code, though, as new code is added to the end of the script
04 28
04 3A <.ReturnValue>
If you don't like pseudo-code, you can do this in hex:

OBJECT=XGStrategySoldier.IsASpecialSoldier:AUTO
[BEFORE_HEX]
04 27
04 28
04 3A C7 53 00 00
[AFTER_HEX]
04 27
//fit your new code here
//patcher will recalculate serial size automatically, but memory size will be wrong
//you will need to calculate memory size and
//all the jump offsets in your code manually (use UEE tokens view for help)
04 28
04 3A C7 53 00 00
REL_OFFSET=0x28
UNSIGNED=//manually calculated memory size here
BTW, a piece of good news for those who fear of pseudo-code. :wink: I was working on hex2pseudocode decompiler for the last week and I almost finished it. Here's an example of vanilla XGStrategySoldier.IsASpecialSoldier function converted to pdeudo-code:

/*(0x0000/0x0000)*/ 0F 00 <.nmZhang> 21 <ZhangSoldier> 
/*(0x0013/0x000F)*/ 0F 00 <.nmAnnette> 21 <Annette> 
/*(0x0026/0x001E)*/ 07 [@label_0x0150] 84 9A 35 <XComGame.XGTacticalGameCoreNativeBase.TAppearance.iHead> <XComGame.XGTacticalGameCoreNativeBase.TAppearance> 00 00 35 <XComGame.XGTacticalGameCoreNativeBase.TSoldier.kAppearance> <XComGame.XGTacticalGameCoreNativeBase.TSoldier> 00 00 01 <@m_kSoldier> 19 2E <XComGame.XComContentManager> 19 12 20 <Engine.Engine> 0A 00 <Engine.Engine.GetEngine.ReturnValue> 00 1C <Engine.Engine.GetEngine> 16 0A 00 <Engine.Engine.GetContentManager.ReturnValue> 00 1B <GetContentManager> 16 15 00 <XComGame.XComContentManager.GetContentIdFromTag.ReturnValue> 00 1C <XComGame.XComContentManager.GetContentIdFromTag> 24 04 00 <.nmZhang> 16 16 18 [@label_0x0091] 9A 35 <XComGame.XGTacticalGameCoreNativeBase.TAppearance.iHead> <XComGame.XGTacticalGameCoreNativeBase.TAppearance> 00 00 35 <XComGame.XGTacticalGameCoreNativeBase.TSoldier.kAppearance> <XComGame.XGTacticalGameCoreNativeBase.TSoldier> 00 00 01 <@m_kSoldier> 19 2E <XComGame.XComContentManager> 19 12 20 <Engine.Engine> 0A 00 <Engine.Engine.GetEngine.ReturnValue> 00 1C <Engine.Engine.GetEngine> 16 0A 00 <Engine.Engine.GetContentManager.ReturnValue> 00 1B <GetContentManager> 16 15 00 <XComGame.XComContentManager.GetContentIdFromTag.ReturnValue> 00 1C <XComGame.XComContentManager.GetContentIdFromTag> 24 04 00 <.nmAnnette> 16 16 16 
/*(0x014E/0x00DE)*/ 04 27 
[#label_0x0150]
/*(0x0150/0x00E0)*/ 04 28 
/*(0x0152/0x00E2)*/ 04 3A <XGStrategySoldier.IsASpecialSoldier.ReturnValue> 
/*(0x015C/0x00E8)*/ 53 
Now existing functions will be easy to rewrite, as all the references and jumps are decompiled and replaced with labels. Edited by wghost81
Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...