jefeonwuka Posted November 20, 2014 Share Posted November 20, 2014 So I'm taking baby steps into editing upks. My first attempt is basically to rewrite an existing function. Chosen XGStrategyGame.UpdateHeader because that's one I eventually want to change (hope to add Power, Elerium, Alloys to all screens). Using modfiles with PatchUPK because it seems the easiest path, partly because it can quickly revert and partly because of the pseudocode. That's where I'm finding the problem now: I want to make a replacement that uses pseudocode just as a proof that the pseudocode functions. I managed to get it to patch successfully, so it's finding existing objects. Now the game crashes whenever I have the test mod on. Wondering if anyone's got a suggestion. This is what my test code looks like (excluding the modfile header): UPK_FILE=XComStrategyGame.upk OBJECT=XGHeadquartersUI.UpdateHeader:AUTO [REPLACEMENT_CODE] //let (strc strLabel strc txtCash inst m_kHeader) (GetResourceLabel 0) 0F 35 <XComGame.XGTacticalScreenMgr.TLabeledText.strLabel> 35 <XGHeadquartersUI.THQHeader.txtCash> 01 <@m_kHeader> 1B <XGScreenMgr.GetResourceLabel> 25 16 0F 35 <XComGame.XGTacticalScreenMgr.TLabeledText.StrValue> 35 <XGHeadquartersUI.THQHeader.txtCash> 01 <@m_kHeader> 1B <XGScreenMgr.ConvertCashToString> 1B <XGScreenMgr.GetResourceLabel> 24 25 16 16 0F 35 <XComGame.XGTacticalScreenMgr.TLabeledText.iState> 35 <XGHeadquartersUI.THQHeader.txtCash> 01 <@m_kHeader> <%i 6> 14 2D 35 <XComGame.XGTacticalScreenMgr.TLabeledText.bNumber> 35 <XGHeadquartersUI.THQHeader.txtCash> 01 <@m_kHeader> 27 04 0B 53 Sorry the comments aren't complete; I started going back through to write them but decided to test it first. It should match up pretty closely to the existing function hex-wise. Thanks for any help. Link to comment Share on other sites More sharing options...
wghost81 Posted November 21, 2014 Share Posted November 21, 2014 (edited) Structure member references are incorrect. They should look like this://m_kHeader.txtCash.strLabel = GetResourceLabel(0) 0F 35 <XComGame.XGTacticalScreenMgr.TLabeledText.strLabel> <XComGame.XGTacticalScreenMgr.TLabeledText> 00 00 35 <XGHeadquartersUI.THQHeader.txtCash> <XGHeadquartersUI.THQHeader> 00 01 01 <@m_kHeader> 1B <GetResourceLabel> 25 16 UE Explorer disassembled tokens view can help you to understand bytecode structure better. Edited November 21, 2014 by wghost81 Link to comment Share on other sites More sharing options...
jefeonwuka Posted November 22, 2014 Author Share Posted November 22, 2014 Thanks for the correction. I checked out the tokens view but it hasn't really helped me understand why you added the extra "00 00" before the second "35," for instance. The hex values I'd seen for it don't include the extra bytes; structmember references are just listed "35". Link to comment Share on other sites More sharing options...
wghost81 Posted November 22, 2014 Share Posted November 22, 2014 That's just the typical hex code for structure member access. We learned it by disassembling tokens with UEE and comparing the results. But yes, there are still things we don't fully understand. Structure members can be accessed with the code: 35 <Struct.Member> <Struct> 00 00 or 35 <Struct.Member> <Struct> 00 01 It is not clear why the last byte is sometimes set to 0 and sometimes to 1. Link to comment Share on other sites More sharing options...
jefeonwuka Posted November 26, 2014 Author Share Posted November 26, 2014 Thanks for the info. Took a bit of tinkering but I got the game to start up with the mod patched on. Will start exploring a bit more. Link to comment Share on other sites More sharing options...
jefeonwuka Posted November 26, 2014 Author Share Posted November 26, 2014 (edited) Hm, maybe not. Just noticed that I'd had MODDED_HEX in there, so it looks like it wasn't patching the whole thing over. This is my code now: 0F 35 <XComGame.XGTacticalScreenMgr.TLabeledText.strLabel> <XComGame.XGTacticalScreenMgr.TLabeledText> 00 00 35 <XGHeadquartersUI.THQHeader.txtCash> <XGHeadquartersUI.THQHeader> 00 01 01 <@m_kHeader> 00 00 1B <GetResourceLabel> 00 00 25 16 0F 35 <XComGame.XGTacticalScreenMgr.TLabeledText.StrValue> <XComGame.XGTacticalScreenMgr.TLabeledText> 00 00 35 <XGHeadquartersUI.THQHeader.txtCash> <XGHeadquartersUI.THQHeader> 00 01 01 <@m_kHeader> 00 00 1B <ConvertCashToString> 00 00 1B <GetResourceLabel> 00 00 24 00 16 16 0F 35 <XComGame.XGTacticalScreenMgr.TLabeledText.iState> <XComGame.XGTacticalScreenMgr.TLabeledText> 00 00 35 <XGHeadquartersUI.THQHeader.txtCash> <XGHeadquartersUI.THQHeader> 00 00 01 <@m_kHeader> 06 14 2D 35 <XComGame.XGTacticalScreenMgr.TLabeledText.bNumber> <XComGame.XGTacticalScreenMgr.TLabeledText> 00 00 35 <XGHeadquartersUI.THQHeader.txtCash> <XGHeadquartersUI.THQHeader> 00 01 01 <@m_kHeader> 00 00 27 04 0B 53 I'm using REPLACEMENT_CODE now but that always seems to set it at the wrong Offset. Setting the REL_OFFSET to 48 and using MODDED_CODE hasn't given much difference, though that is where my code is starting. Edited November 26, 2014 by jefeonwuka Link to comment Share on other sites More sharing options...
wghost81 Posted November 26, 2014 Share Posted November 26, 2014 (edited) Because it's not hex, it's code. So you need to use MODDED_CODE section/key. First version of the Patcher had just FILE, OFFSET and MODDED_HEX functionality. For the sake of backward compatibility I left all those unchanged and added a lot of new keys/sections for the new features. REPLACEMENT_CODE is used to replace an entire script. It finds the script offset automatically and automatically resizes it to fit a new data if AUTO modifier is set. MODDED_CODE, on the other hand, needs a code offset to be set manually with REL_OFFSET command, for example. PatchUPK_Readme.txt has all these thing explained. I realize it might seem complicated, but that's like an entirely new script language for XCOM patching you have to learn. Personally, I use REPLACEMENT_CODE when I need to replace an entire script, because it does all the calculations for me. And when I need to replace a part of the code, I use BEFORE_CODE/AFTER_CODE pair to find some code and replace it with a new one. Edited November 26, 2014 by wghost81 Link to comment Share on other sites More sharing options...
jefeonwuka Posted November 26, 2014 Author Share Posted November 26, 2014 (edited) I understand that. The problem is that REPLACEMENT_CODE does not take it to the appropriate point in the script, it takes it 8 bytes earlier. When I use MODDED_CODE with a REL_OFFSET, it replaces the appropriate code segment but the game still CTDs. The problem is not the section/key I am using, as I already explained. There's something wrong with the code but I cannot figure out what it is. The only reason I mentioned MODDED_HEX at all is because it was a mistake which caused me to think that I had got it to work when it hadn't. I felt it necessary to explain why I was bumping the thread again. I am not using MODDED_HEX now and I know I'm not supposed to use it in this situation. Edited November 26, 2014 by jefeonwuka Link to comment Share on other sites More sharing options...
raargharg Posted November 26, 2014 Share Posted November 26, 2014 (edited) How do you know what to put in (the hex) besides the actual script? Let's say I want to addif(!m_kUnit.IsMine() && GetPrimaryTarget().IsMine()) { // End:0x263 if((m_kUnit.GetAI() != none) && !m_kUnit.GetAI().CanCrit()) { m_bCritical = false; } } to a function, how do I know what to put in the PatcherGUI? Is there a tutorial for this? I managed to use BEFORE/AFTER HEX but not sure what to do for code. Currently a little lost reading the PATCHUPK readme. Edit: Wasn't aware this was such a manually intensive process :/Gonna see if I can figure out how to turn something like m_kUnit.IsMine to the <whatever><these><need to be> Edited November 26, 2014 by raargharg Link to comment Share on other sites More sharing options...
wghost81 Posted November 27, 2014 Share Posted November 27, 2014 (edited) jefeonwuka, I don't know how to explain it better, but REPLACEMENT_CODE replaces the whole script from the very beginning to the very end. It doesn't take you 8 bytes earlier. But it automatically calculates and rewrites script virtual and serial sizes and this is probably the thing you're mistaking for the wrong offset. When you're using REPLACEMENT_CODE, you have to re-write an entire script, including return and EOS tokens, otherwise the game will crash. Correct ones for XGHeadquartersUI.UpdateHeader are//return 04 0B //EOS 53 Add those to the end of your script and everything will work. If you're using MODDED_CODE, you have to either keep virtual size unchanged or recalculate and rewrite it manually. PS It looks like 1B <GetResourceLabel> 00 00 24 00 16 has two extra zero bytes and should look like 1B <GetResourceLabel> 24 00 16. Furthermore, GetResourceLabel requires int, not enum, so it has to be either 25 (zero const token) or 2C 00: 1B <GetResourceLabel> 25 16. There are also errors in lines 3 and 4: 06 instead of 2C 06 and extra zeros between variable reference and "true" token 27. I suspect, you haven't tried to open your script with UEE. Please, do it each time before running the game to make sure it decompiles correctly. raargharg, open "Token view" in UE Explorer and you'll see the bytecode for the decompiled function. I used this tutorial for hex editing: http://wiki.tesnexus.com/index.php/Hex_editing_UPK_files It covers the basics of XCOM bytecode. And Patcher's pseudo code basically replaces 4-byte hex references with named references. Edited November 27, 2014 by wghost81 Link to comment Share on other sites More sharing options...
Recommended Posts