Jump to content

wghost81

Premium Member
  • Posts

    1186
  • Joined

  • Last visited

Everything posted by wghost81

  1. If you download the ods table I linked (or open it with GoogleSheets), you see that table in two different forms (google gives a print preview and this one wasn't made for printing). I believe the first page is close to one of the variants you suggested. But IMO it isn't that clear to understand. The thing with 0x61-0x6F tokens is that they allow to extend native table beyond 256 functions. Since tokens are 1 byte in size, they can hold values from 0x00 to 0xFF, which gives 256 possible values. And there are way more native functions in UE than 256. To solve this problem UE uses 0x60-0x6F tokens as markers which indicate that the index of this function exceeds 0x00-0xFF range and that the next token should be used to identify a native function with index more than 0xFF. This effectively makes extended native function tokens 2 bytes long and increases possible indexes range up to 0xFFF. Token 0x60 marks the beginning of extended native tokens group and never actually used in scripts. I believe they did it to save memory space, as the most frequently used tokens are 1 byte long and less frequently used extended tokens are 2 bytes long. So, indexes 0x00-0x5F belong to the most frequently used tokens, which define basic unrealscript operators. Those operators are defined in C++ code and are not declared inside Core and Engine unrealscript classes. Indexes 0x70 to 0xFF are used for common operations, like comparison and summation. Corresponding functions are declared in base unrealscript classes (like Object and Actor) but defined in C++ code. All the other functions with indexes from 0x100 to 0xFFF are declared in unrealscript classes and defined in C++ code. Such functions have native(XXX) keyword, which indicates that they are a part of native table (XXX is a native table index). Basic unrealscript functions have specific hex data format and all the other native functions follow the same pattern: <ExtendedNativeToken> <FunctionToken> <Expression1> ... <ExpressionN> <EndParmExp> For tokens 0x70 through 0xFF <ExtendedNativeToken> (0x60) is omitted to save space. For tokens 0x100 through 0xFFF <ExtendedNativeToken> = 0x60 + (0xF00 & NativeTableIndex) >> 2 <FunctionToken> = 0x0FF & NativeTableIndex So, for the function with index 921 = 0x399 <ExtendedNativeToken> = 0x60 + (0xF00 & 0x399) >> 2 = 0x60 + 0x300 >> 2 = 0x63 <FunctionToken> = 0x0FF & NativeTableIndex = 0x0FF & 0x399 = 0x99 The shortened version of this explanation is given inside tokens table on wiki page. Since all the extended functions follow the same pattern, their hex data format is identical. So, to make the long story short, the table is indeed long and 0x61, 0x62, etc. tokens mark the different "pages" of the table. I agree there have to be more explanations on how it works, but right now I only copied my working data from ods document. The same way, cast tokens are belong to the different table, as they are not reused tokes but a second part of 2 bytes long token 0x38. Since tokens 0x00 through 0x5F do not have associated Package.Class and have different hex format and a lot of notes, we can make a separate table just for them alone. Then we can put all the explanations about 0x60-0x6F group and all the other tokens can be put into separate table with Dec, Hex, Name, Expression and Package.Class rows. What do you think? UPD: Yes, I agree to provide an update on hex editing upk files. I won't make it PatchUPK specific and will try to stick to simple hex examples. But it's a lot of work and I hope the others will share their thoughts and experience on this matter either. :wink:
  2. Thanks for the feedback. :) You don't need to fix jump offsets with pseudo-code and that's the beauty of it. :smile: All the existing jumps are already marked with labels by decompiler, you just need to use labels in your new code instead of values.
  3. Since there are many new modders joining our community I suggest reviewing and updating wiki articles on XCOM modding as some of them are not up to date. I took a liberty to update an article on hex values: http://wiki.tesnexus.com/index.php/Hex_values_XCOM_Modding I haven't hand-crafted those tables (I mean wiki formatting) :smile: , but reformatted them with regexp from the document I created while I was working on pseudo-code decompiler: https://drive.google.com/open?id=0B5MAcyqYBx4dSjQ3Nk05akFfVEE&authuser=0 Any suggestions on how this can be improved are welcomed. I also suggest updating this article: http://wiki.tesnexus.com/index.php/Hex_editing_UPK_files It's getting a bit old and there is a lot of new data we can add into it to make learning curve for newcomers a bit smoother. :smile:
  4. No, you can't. Resource hacker modifies exe file and you need to modify upk file. Long War has it's own forum and there is a topic about modding: http://forums.nexusmods.com/index.php?/topic/1151348-modding-long-war/ Try searching/asking for the solution there. There is a lot of Nexus wiki articles on how to edit XCOM upk files. Try starting with this one: http://wiki.tesnexus.com/index.php/Hex_editing_UPK_files
  5. Updated the code on github and uploaded a new release (to github) for testing. I will update Nexus files after I finish some QOL changes for PatcherGUI.
  6. No, you'll need to hex edit upk to change alien squad composition.
  7. 2EliotVU: Tokens view consumes primitive cast token (0x38) and extended native function tokens (0x61 to 0x6F) if those are at the beginning of the line. It happens with both tokens and disassembled tokens view. I'm using 1.2.6.0 UEE version.
  8. And another piece of good news: seems I finally found a relatively easy solution for auto-calculating skip offsets. Example: 1B <Game> 16 [@] <XGStrategy.GetDifficulty.ReturnValue> 00 ( 1B <GetDifficulty> 16 ) [@] code with no label name defined signals patcher to look for ( ) pair, calculate mem_size = mem_pos_of_) - mem_pos_of_( and replace [@] code with 2 bytes of mem_size. Stacked parentheses should also be resolved properly. Laziness is indeed a driving force of progress. :smile: Manual calculations are boring and I got too lazy to continue doing these. :smile:
  9. I'm currently working on hex2pseudocode decompiler to make scripting with pseudo-codes easier. I've almost finished the decompiler but I'm kinda stuck with indentations at this point. :( I always thought highly of Eliot and UEE, but now that I've implemented partial decompilation myself, I'm starting to adore both. :) All this code formatting drives me crazy. :) This is an example of how the output looks like right now: /*(0x0000/0x0000)*/ 1B <CheckForSecondWave> 16 /*(0x000A/0x000A)*/ 19 01 <@m_kHQ> 0A 00 <NullRef> 00 1B <InitNewGame> 16 /*(0x0029/0x0021)*/ 19 01 <@m_kGeoscape> 0A 00 <NullRef> 00 1B <InitNewGame> 16 /*(0x0048/0x0038)*/ 19 01 <@m_kWorld> 0A 00 <NullRef> 00 1B <StartGame> 16 /*(0x0067/0x004F)*/ 19 01 <@m_kAI> 0A 00 <NullRef> 00 1B <InitNewGame> 16 /*(0x0086/0x0066)*/ 19 19 2E <XComGame.XComOnlineProfileSettings> 19 12 20 <Engine.Engine> 0A 00 <Engine.Engine.GetEngine.ReturnValue> 00 1C <Engine.Engine.GetEngine> 16 0A 00 <Engine.Engine.GetProfileSettings.ReturnValue> 00 1B <GetProfileSettings> 16 09 00 <XComGame.XComOnlineProfileSettings.Data> 00 01 <XComGame.XComOnlineProfileSettings.Data> 0A 00 <NullRef> 00 1B <IncGamesPlayed> 16 /*(0x00EF/0x00AF)*/ 07 [@label_0x0106] 2D 01 <@m_bDebugStart> /*(0x00FC/0x00B8)*/ 1B <DebugStuff> 16 /*(0x0106/0x00C2)*/ [#label_0x0106] /*(0x0106/0x00C2)*/ 07 [@label_0x0181] 82 81 2D 01 <@m_bControlledStart> 16 18 0D 00 81 2D 01 <@m_bDebugStart> 16 16 /*(0x0126/0x00DA)*/ 61 00 1E <%f 0.1> 16 /*(0x012E/0x00E2)*/ 19 1B <GEOSCAPE> 16 0D 00 <NullRef> 00 1B <PreloadSquadIntoSkyranger> 24 01 28 16 /*(0x0151/0x0101)*/ 07 [@label_0x0169] 1B <AreDropshipSoldiersStillLoading> 16 /*(0x015E/0x010E)*/ 61 00 1E <%f 0.1> 16 /*(0x0166/0x0116)*/ 06 [@label_0x0151] /*(0x0169/0x0119)*/ [#label_0x0169] /*(0x0169/0x0119)*/ 07 [@label_0x0181] 1C <Core.Object.IsAsyncLoadingWrapper> 16 /*(0x0176/0x0122)*/ 61 00 1E <%f 0.1> 16 /*(0x017E/0x012A)*/ 06 [@label_0x0169] /*(0x0181/0x012D)*/ [#label_0x0181] /*(0x0181/0x012D)*/ 07 [@label_0x01AF] 19 1B <PRES> 16 0A 00 <XComHQPresentationLayer.IsBusy.ReturnValue> 00 1B <IsBusy> 16 /*(0x01A4/0x014C)*/ 61 00 1E <%f 0> 16 /*(0x01AC/0x0154)*/ 06 [@label_0x0181] /*(0x01AF/0x0157)*/ [#label_0x01AF] /*(0x01AF/0x0157)*/ 19 2E <XComGame.XComOnlineEventMgr> 19 2E <Engine.GameEngine> 12 20 <Engine.Engine> 0A 00 <Engine.Engine.GetEngine.ReturnValue> 00 1C <Engine.Engine.GetEngine> 16 09 00 <Engine.GameEngine.OnlineEventManager> 00 01 <Engine.GameEngine.OnlineEventManager> 0A 00 <NullRef> 00 1B <ResetAchievementState> 16 /*(0x020B/0x0193)*/ 07 [@label_0x0225] 2D 01 <@m_bDebugStart> /*(0x0218/0x019C)*/ 1B <GoToHQ> 16 /*(0x0222/0x01A6)*/ 06 [@label_0x02B2] /*(0x0225/0x01A9)*/ [#label_0x0225] /*(0x0225/0x01A9)*/ 07 [@label_0x0278] 2D 01 <@m_bControlledStart> /*(0x0232/0x01B2)*/ 0F 01 <@m_kSetupPhaseManager> 1C <Engine.Actor.Spawn> 20 <Class.XGSetupPhaseManager> 17 4A 4A 4A 4A 4A 4A 16 /*(0x0256/0x01CA)*/ 19 01 <@m_kSetupPhaseManager> 0A 00 <NullRef> 00 1B <StartNewGame> 16 /*(0x0275/0x01E1)*/ 06 [@label_0x02B2] /*(0x0278/0x01E4)*/ [#label_0x0278] /*(0x0278/0x01E4)*/ 07 [@label_0x0292] 2D 01 <@m_bTutorial> /*(0x0285/0x01ED)*/ 1B <GoToTutorial> 16 /*(0x028F/0x01F7)*/ 06 [@label_0x02B2] /*(0x0292/0x01FA)*/ [#label_0x0292] /*(0x0292/0x01FA)*/ 19 1B <GEOSCAPE> 16 0A 00 <NullRef> 00 1B <TakeFirstMission> 16 /*(0x02B2/0x0216)*/ [#label_0x02B2] /*(0x02B2/0x0216)*/ 08 /*(0x02B3/0x0217)*/ 0C <Begin> <%u 0> <None> <%u 65535> /*(0x02CC/0x0230)*/ 53 It is directly usable by PatcherGUI/PatchUPK. Indentations are weird for if-else (last else with no if is not indented) and for default case, but after several attempts on making it look prettier I gave up and decided it wasn't worth it. I don't know if I'm able to generate UEE-like decompiled human-readable code to add it as comments but if I have time, I'll try to do it. I'm about to do some more tests and after that I'll release the decompiler for everyone to use.
  10. Always read the readme, the readme is your friend. ;)
  11. Expanding map borders might not be so simple as out-of-border objects are not fully functional and serve as decorations. EU and EW are basically two different incompatible games. To make EU maps work in EW we'd have to re-cook them which isn't possible atm. BTW, Beagle, have you tried random bomb missions mod already? :smile:
  12. Thousands of other people can, so problem is most probably on your side. And right now you're not very informative. As a result I can't be very helpful. To understand how this "thing" works and why XCOM modding is not easy, please, read the readme (accessible by pressing F1 key while running PatcherGUI or directly inside a program folder). Pay close attention to section named "Reporting bugs and asking questions" while you're at it. Again: what exactly are you trying to do? What version of PatcherGUI do you have? How you have installed it? Which game version do you own? Where is program debug log and if there is none, how exactly error message looks like? PS We are talking about PatcherGUI here or not? Please, provide the full name of an utility and a link to Nexus download page. Because it's a second time I have to guess it by error messages and those aren't very clear.
  13. Yes, tokens for different data types comparison are different. Here is the document I created while I was working on hex-to-pseudo-code decompiler for use with patcher. It may seem messy as I made it for myself, but you can find some useful information on tokens there, including data types for different operations. UEE ignores memory sizes, so the code might look well in there but still CTD in game. The problem with this particular code is that skip sizes should be in memory bytes, not serial bytes. Since both expressions contain three object references, their memory size has 3*4=12 more bytes. BTW, null references can be particularly painful here as they are hard to spot (all zeroes), but still have 4 additional bytes of memory size.
  14. First of all: what exactly are you trying to do? Second: what other mods (including TexMod) do you have installed?
  15. Ternary condition has two skip tokens inside you have to set up correctly to get it to work. Syntax: 45 <Expr(Cond)> <MemSize> <Expr(IfTrue)> <MemSize> <Expr(IfFalse)> Each MemSize is 2 bytes short integer and is equal to memory size of the following expression. Specifying the wrong value here will cause the game to crash, but if memory serves it usually happens on execution, not on startup.
  16. 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.
  17. 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
  18. >I set the script size to 0x1858 which is quite a bit larger than it needs to be. It doesn't have to be exact does it? Quite opposite: it has to be exact value or the game will crash. Random big value allows you to decompile the script with UEE and obtain the exact memory size value. As I wrote earlier, now you have to open your script in UEE and go to View -> View Tokens. Scroll down to the last line to see something similar to (AAA/BBB) [53] EOS(1/1) Memory size of the script is equal to AAA+1 and serial size is equal to BBB+1. Note that both are in hex. Yes, for all XCOM scripts 0x28 is a standard memory size offset, you can use it safely.
  19. You forgot to adjust script memory size. REL_OFFSET=0x28 [MODDED_HEX] XX XX XX XX YY YY YY YY XX XX XX XX here sets memory size and YY YY YY YY - serial size. Alternatively you can use this code: REL_OFFSET=0x28 UNSIGNED=0xAAAAAAAA 0xAAAAAAAA here is script memory size in hex representation. In UEE go to View -> View Tokens. Scroll down to the last one to see something similar to (AAA/BBB) [53] EOS(1/1) Memory size of the script is equal to AAA+1 and serial size is equal to BBB+1. Note that both are in hex. If there is no EOS token at the end of your script, it means that current memory size is too small. Increase it to some random big value, like twice of the current value, and try again.
  20. 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.
  21. Which tool do use for modding? PatcherGUI/PatchUPK or UPKModder? Both can deal with resizing an object, but in a different manner.
  22. For vanilla EU and EW: http://www.nexusmods.com/xcom/mods/474
×
×
  • Create New...