Solver Posted October 20, 2012 Share Posted October 20, 2012 Well, I never knew how the engine works - it might have been programmed to check unreachable code as well for all I knew. But yes, what I'm getting at it what kanet is saying, or at least so it seems so far. Leaving a function call with invalid parameters, or leaving code that prepares parameters while the function call itself is removed, makes the game crash - even if the code appears to be correct upon inspection in UE Explorer. It's actually difficult for me right now, I easily changed two functions to return true, but can't for the life of me make a third function return true. Link to comment Share on other sites More sharing options...
dreadylein Posted October 20, 2012 Share Posted October 20, 2012 (edited) mhm did you tryed 0x0b ? maybe you can just fill it with nops depends how the engine handle this token Edited October 20, 2012 by dreadylein Link to comment Share on other sites More sharing options...
Solver Posted October 20, 2012 Share Posted October 20, 2012 Wrote the bytecode from scratch :D Doesn't correspond to proper UE code, there's something about it that I do not understand. A certain byte, I think. Here's code for two almost identical functions, both of which are bool functions returning a single variable, as in bool () { return m_someVar; } - these are some of the simplest functions possible. Image First 16 bytes are the same except for what appears to be the function ID. Second 16 bytes are equal except the byte 0x18, which points to the object where the function's return value will be stored. It is the byte 0x20 that I do not understand, interpreting it either as a pointer to an object or a name makes no sense, it's not really related to what the function does. Bytes 0x24 and 0x25 may be storage space for the parameters, as byte 0x28 (value 0x16) is an opcode indicating that the parameter list is over. Byte 0x30 (value 0x04) indicates that a return value follows. Byte sequence 0x2D 0x01 says that it's a boolean instance variable, and next the byte 0x33 is a pointer to the m_someVar variable. Sequence 0x04 0x3A indicates that it should be returned as an int type, followed by the location for the return value in byte 0x39. Byte 0x3D says the script is over, then there's a reference again to a variable (not really sure why), and the bytes 0x45 and 0x46 respectively refer to the name of the function, and a comparison operator (probably the operator to use to compare this function's return value). Mind you, if the bytes 0x30 and 0x31 get just changed to 0x04 0x27, that returns true, and the subsequent reference to a variable remains there without disturbing anything. I tried using a code built like this for a function that calls another function, but it doesn't work at all. My problem is likely the byte 0x20, I have no idea what goes there. Link to comment Share on other sites More sharing options...
kanet32 Posted October 20, 2012 Share Posted October 20, 2012 This may be a silly question, but have you tried seeing what UE Explorer decompiles it to? Or does UE Explorer choke on it as well? I'm assuming you've already tried this, but since you haven't mentioned it, I figure it's possible you didn't even know about UE Explorer and have been reading through all the scripts in bytecode all this time. (If so, respect. That's some Story of Mel s*** there.) Link to comment Share on other sites More sharing options...
Solver Posted October 20, 2012 Share Posted October 20, 2012 I'm pretty hardcore but I am using UE Explorer :D And it chokes on that bytecode I write from scratch to replace that certain function. I know I got the function ID and its return address right, from the existing code, so there's only a couple of places I might have gotten wrong. Will see... Link to comment Share on other sites More sharing options...
kanet32 Posted October 20, 2012 Share Posted October 20, 2012 (edited) Well, I can tell you that most of the times I've seen any bytes over 0x60 that weren't constants, they were function calls. The fact that a few bytes later you have 0x16 (EndFunctionParams) seems to support that. So, I'd wager that the C3 04 and BE 04 are both function calls. Since they're little-endian, it's actually 0x04C3 and 0x04BE, which would be 1219 and 1214, respectively. Depending on which UPK you're looking at, those could be different functions. In XComGame.upk, they're... From ImportTable.txt:1219 = Function'Engine.ResetDesiredRotation'1214 = Function'Engine.PostBeginPlay' Or possibly, from ExportTable.txt:1214 = ObjectProperty'UIScreen.m_kTacMgr'1219 = IntProperty'UIScreen.GetCurrentView.ReturnValue'But those are both properties, not function calls, and the 0x16 really seems to imply function calls. Alternatively, if you're looking in XComStrategyGame.upk...From ExportTable.txt:1214 = Function'UIBriefing.SetupIntroBink'1219 = ObjectProperty'UIBriefing.OnMovieLoaded.LoadedArchetype' The first one is a function; if the second block of code in your screenshot is your modified code, maybe the problem is that your changed code is calling an ObjectProperty as though it were a function? Maybe? I haven't really dug that deep into the bytecode, so this is all guesswork. EDIT: Just re-read what you wrote, and you said both functions are from the game and just return a value, so now I have no idea why there'd be a function call in there. Maybe it's something like C# properties, where accessing a property actually calls a function? I'm used to C++, myself, where everything is much more ordered and reliable. Variables are variables and functions are functions. Edited October 20, 2012 by kanet32 Link to comment Share on other sites More sharing options...
Solver Posted October 20, 2012 Share Posted October 20, 2012 (edited) Both functions in my screenshot are existing unmodified functions of the same form, to make conclusions about how the simplest function works. I've seen that they can correspond to indexes also, 1214 or 1219. Doesn't make sense. This is XComGame.upk, and neither of the functions at those indices makes sense. The two functions I looked at there relate to weapon properties. What does PostBeginPlay (an initialization function) or a map rotation function have to do with it? Nothing probably. UE Explorer shows various interpretations, as references to objects/names/etc., but nothing really seems to make sense. Also, these are both super-simple functions. They should not call anything. EndFunctionParams is there, I assume, for this function's own parameter list, not for a function that it calls. Calling another function seems to require a 0x1B (VirtualFunction) opcode, or a FirstNative opcode, or somesuch. These are mostly guesses, this is after all the first time I am looking at UE code. EDIT: And no, doesn't look like C# properties. Accessing an instance variable is pretty straightforward. Sequence 0x2D, 0x01 and a third byte does in these two cases. 0x2D means a boolean type, 0x01 means an instance variable in this class, the third byte is the index of said variable. Definitely C++ style more than C# property style. Edited October 20, 2012 by Solver Link to comment Share on other sites More sharing options...
kanet32 Posted October 20, 2012 Share Posted October 20, 2012 Yeah, I missed the bit where you said they were just accessor methods. (And even still, it was just a wild guess on my part.) Sorry, I've no idea here. If I had some time, I'd try reading through them following the logic from that UnrealScript decompiler I posted a while back (BytecodeReader.cs, which I assume is what you're looking at to find the instruction codes) and see if I could figure out what was happening there. To be honest, at this point I'd probably recommend not trying to make such large changes to the compiled scripts. My guess is pretty soon someone with knowledge of the UDK will come in and give us instructions on how to set it up to decompile and recompile UnrealScript. There's a lot of room to manoeuvre just in changing constants or operators around for the time being. (Though, if you do continue forging ahead learning the bytecode, by all means continue letting us know what you find.) Link to comment Share on other sites More sharing options...
Solver Posted October 20, 2012 Share Posted October 20, 2012 Hmm, do you know if the class itself stores its length somewhere? I observe that changing a function's length messes up what UE Explorer sees, though the functions themselves do not store their length. Perhaps there is some padding required or something to make functions align correctly. That is a possibility. I didn't of course think these would be large changes - just the most primitive stuff by making some functions return true, but that's also non-trivial. If scripts can be recompiled into the UPK files properly through someone's knowledge or a Firaxis tool, great! Definitely looking forward to that. Link to comment Share on other sites More sharing options...
dreadylein Posted October 20, 2012 Share Posted October 20, 2012 (edited) mhh maybe we have some version problems here ? :D 1214 m_bInited1219 InitMgr Which looks more promising Edit: Mh there nearly must be some kind of lengh for the objects, even if only indirect through the name to offset thing in the upk Edited October 20, 2012 by dreadylein Link to comment Share on other sites More sharing options...
Recommended Posts